Set-up packages // libraries and prepare for data import:
## Uncomment install.packages and run outside of notebook environment:
## install.packages(c("psych" ,"xtable", "tidyverse", "jsonlite", "likert", "ggplot2", "ploty", "mosaic"))
library(psych)
library(likert)
Loading required package: ggplot2
Attaching package: ‘ggplot2’
The following objects are masked from ‘package:psych’:
%+%, alpha
Loading required package: xtable
library(jsonlite)
library(ggplot2)
library(mosaic)
Loading required package: dplyr
Attaching package: ‘dplyr’
The following object is masked from ‘package:likert’:
recode
The following objects are masked from ‘package:stats’:
filter, lag
The following objects are masked from ‘package:base’:
intersect, setdiff, setequal, union
Loading required package: lattice
Loading required package: ggformula
New to ggformula? Try the tutorials:
learnr::run_tutorial("introduction", package = "ggformula")
learnr::run_tutorial("refining", package = "ggformula")
Loading required package: mosaicData
Loading required package: Matrix
The 'mosaic' package masks several functions from core packages in order to add
additional features. The original behavior of these functions should not be affected by this.
Note: If you use the Matrix package, be sure to load it BEFORE loading mosaic.
Attaching package: ‘mosaic’
The following object is masked from ‘package:Matrix’:
mean
The following objects are masked from ‘package:dplyr’:
count, do, tally
The following object is masked from ‘package:ggplot2’:
stat
The following objects are masked from ‘package:psych’:
logit, read.file, rescale
The following objects are masked from ‘package:stats’:
binom.test, cor, cor.test, cov, fivenum, IQR, median, prop.test, quantile, sd, t.test, var
The following objects are masked from ‘package:base’:
max, mean, min, prod, range, sample, sum
library(plotly)
Attaching package: ‘plotly’
The following object is masked from ‘package:mosaic’:
do
The following object is masked from ‘package:ggplot2’:
last_plot
The following object is masked from ‘package:stats’:
filter
The following object is masked from ‘package:graphics’:
layout
source("http://pcwww.liv.ac.uk/~william/R/crosstab.r")
theme_set(theme_classic())
Set-up directories, import and clean data:
rm(list=ls())
setwd("/Users/allieblaising/desktop/bang/R")
getwd()
[1] "/Users/allieblaising/Desktop/bang/R"
dataPath = "../.data"
## Define function to extract survey results:
extractSurvey = function(frame,survey) {
rounds = seq(1,length(frame$results.format[[1]]))
roundResponses = lapply(rounds, function(round) {
getCol = paste("results.",survey,".",round, sep="")
surveyCols = Filter(function(x) grepl(getCol,x),names(frame))
newCols = lapply(surveyCols, function(x) gsub(getCol,paste("results.",survey, sep=""),x) )
surveyFrame = frame[,surveyCols]
if (is.null(newCols)) {return("No newCols")}
names(surveyFrame) = newCols
surveyFrame$id = frame$id
surveyFrame$round = round
surveyFrame$batch = frame$batch
surveyFrame$rooms = frame$rooms
surveyFrame$manipulation = frame$results.manipulationCheck
surveyFrame$blacklist = frame$results.blacklistCheck
return(surveyFrame)
})
return(Reduce(rbind,roundResponses))
}
#Find directory for import (be sure to verify that batch #s align from bangData import and imports below):
batches = dir(dataPath, pattern = "^[0-9]+$" )
completeBatches = Filter(function(batch) {
if (any(dir(paste(dataPath,batch,sep="/")) == "batch.json") && (any(dir(paste(dataPath,batch,sep="/")) == "users.json")) ) {
batchData = read_json(paste(dataPath,batch,"batch.json",sep="/"), simplifyVector = TRUE)
return(any(batchData$batchComplete == TRUE))
}
return(FALSE)
}, batches)
userFiles = lapply(completeBatches, function(batch) {
userFile = read_json(paste(dataPath,batch,"users.json",sep="/"))
print(batch)
print(class(userFile))
print(userFile)
return(flatten(userFile, recursive = TRUE))
})
[1] "1534287515706"
[1] "list"
list()
Error: is.data.frame(x) is not TRUE
More cleaning before visualizations:
## Apply extract survey function to extract the right columns and rows for viability survey:
survey = 'viabilityCheck'
frame <- extractSurvey(overlappingFiles, survey)
## Reduce to vertically combine rows in roundwithRooms list:
finalRounds = as.data.frame(Reduce(rbind,roundsWithRooms))
## Subset incomplete cases from viability survey dataframe:
## MSB: complete.cases doesn't work when there aren't NAs, but empty lists, alternatives rather than subsetting where
## blacklist is empty? Doens't work: test <- complete.cases(data)
data <- frame[frame$manipulation!="",]
## Rename room to rooms so that both are retained in future merge:
data <- rename(data, rooms = "rooms")
## Subset incomplete cases for final rounds dataframe:
data2 <- finalRounds[finalRounds$results.manipulationCheck!="", ]
## Select only variables of interest from final rounds:
data2 = data2 %>% select(id, batch, room, bonus, name, friends,
friends_history, results.condition, results.format,
results.manipulation,results.manipulationCheck,results.blacklistCheck, round)
## Convert to compatible data types before merge (this should be simplified)
data2$batch <- unlist(data2$batch)
data$batch <- unlist(data$batch)
data2$round <- unlist(data2$round)
data2$id <- unlist(data2$id)
## Before merge, data and data2 should ahve the same # of observations
## Merge columns by id, round and batch #s:
data <- left_join(data, data2, by=NULL)
Joining, by = c("id", "round", "batch")
## Subset only observations with batch #s in complete batches
allConditions <- data[data$batch %in% completeBatches, ]
Conditionally assign conditions based on treatment and results column:
## Messy, but robust? Verify, verify, verify.
data <- data %>% mutate(
condition = case_when(
results.condition=='treatment' & results.format=="c(1, 2, 1)" & round==1 ~ "A",
results.condition=='treatment' & results.format=="c(1, 2, 1)" & round==2 ~ "B",
results.condition=='treatment' & results.format=="c(1, 2, 1)" & round==3 ~ "Ap",
results.condition=='treatment' & results.format=="c(1, 1, 2)" & round==1 ~ "A",
results.condition=='treatment' & results.format=="c(1, 1, 2)" & round==2 ~ "Ap",
results.condition=='treatment' & results.format=="c(1, 1, 2)" & round==3 ~ "B",
results.condition=='treatment' & results.format=="c(2, 1, 1)" & round==1 ~ "B",
results.condition=='treatment' & results.format=="c(2, 1, 1)" & round==2 ~ "A",
results.condition=='treatment' & results.format=="c(2, 1, 1)" & round==3 ~ "Ap" ,
results.condition=='control' & results.format=="c(1, 2, 1)" & round==1 ~ "A",
results.condition=='control' & results.format=="c(1, 2, 1)" & round==2 ~ "B",
results.condition=='control' & results.format=="c(1, 2, 1)" & round==3 ~ "Ap",
results.condition=='control' & results.format=="c(1, 1, 2)" & round==1 ~ "A",
results.condition=='control' & results.format=="c(1, 1, 2)" & round==2 ~ "Ap",
results.condition=='control' & results.format=="c(1, 1, 2)" & round==3 ~ "B",
results.condition=='control' & results.format=="c(2, 1, 1)" & round==1 ~ "B",
results.condition=='control' & results.format=="c(2, 1, 1)" & round==2 ~ "A",
results.condition=='control' & results.format=="c(2, 1, 1)" & round==3 ~ "Ap" ,
results.condition=='baseline' & results.format=="c(1, 2, 3)" & round==1 ~ "A" ,
results.condition=='baseline' & results.format=="c(1, 2, 3)" & round==2 ~ "B" ,
results.condition=='baseline' & results.format=="c(1, 2, 3)" & round==3 ~ "C"
))
Set-up for factors for viability questions:
data <- rename(data, "repeatTeam" = results.viabilityCheck.15)
## Remove observations where viability survey wasn't on (remove this line if we want to keep observations with viability off):
data <- na.omit(data)
levels <- c("Strongly Disagree", "Disagree", "Neutral","Agree", "Strongly Agree")
clean <- data %>%
mutate_at(.vars = vars(contains("results.viabilityCheck")), funs(factor(., levels = levels)))
## Viabilitylikert visuals:
## Subset only viabilitySurvey columns and condition column (condition column used to visualize likert responses for conditions)
viabilityLikert <- select(clean, contains("results.viabilityCheck"), "condition", "results.condition")
viabilityLabels = c("1. The members of this team could work for a long time together"
, "2. Most of the members of this team would welcome the opportunity to work as a group again in the future." ,
"3. This team has the capacity for long-term success.",
"4. This team has what it takes to be effective in the future.",
"5. This team would work well together in the future." ,
" 6. This team has positioned itself well for continued success.",
" 7. This team has the ability to perform well in the future. ",
" 8. This team has the ability to function as an ongoing unit." ,
" 9. This team should continue to function as a unit. ",
" 10. This team has the resources to perform well in the future. ",
" 11. This team is well positioned for growth over time. ",
" 12. This team can develop to meet future challenges. ",
" 13. This team has the capacity to sustain itself. ",
" 14. This team has what it takes to endure in future performance episodes.", "condition", "results.condition")
names(viabilityLikert) <- rep(viabilityLabels)
Likert visualizations:
## Likert graph for all viability responses across all conditions (i.e. baseline, control and treatment):
likert.out <- likert(viabilityLikert[-c(15:16)])
plot(likert.out)

## Subset A and Ap (i.e. A prime) responses for treatment group:
# Treatment + A:
treatmentA <- viabilityLikert %>% filter(condition=="A" & results.condition=="treatment")
likert.treatmentA <- likert(treatmentA[-c(15:16)])
plot(likert.treatmentA)

# Treatment + Ap:
treatmentAp <- viabilityLikert %>% filter(condition=="Ap" & results.condition=="treatment")
likert.treatmentAp <- likert(treatmentAp[-c(15:16)])
plot(likert.treatmentAp)

# Treatment + B:
treatmentB <- viabilityLikert %>% filter(condition=="B" & results.condition=="treatment")
likert.treatmentB <- likert(treatmentB[-c(15:16)])
plot(likert.treatmentAp)

## Customize code above to filter on other conditions and treatments of interest.
Exploratory data analysis part #1:
## Create a new dataframe that converts factors to numeric for statistical analyses:
stats <- clean %>% mutate_if(is.factor, as.numeric)
for (i in 1:nrow(stats)) {
stats$sum[i] <- sum(stats[i,1:14])
}
stats$median <- median(stats$sum)
stats$mean <- mean(stats$sum)
## Revalue repeat team: keep plyr b/c some weird R stuff requires library to be called directly (recode values to )
stats$repeatTeam <- plyr::revalue(stats$repeatTeam, c("Yes"="0", "No"="1"))
stats$repeatTeam <- plyr::revalue(stats$repeatTeam, c("Keep this team"="0", "Do not keep this team"="1"))
## Convert to compatible classes for team grouping:
stats$repeatTeam <- as.numeric(stats$repeatTeam)
stats$results.condition <- unlist(stats$results.condition)
stats$results.format <- as.character(stats$results.format)
stats$room <- unlist(stats$room)
## Dplyr to group teams and summarise variables for each group: group_by to find teams and summarise to compact individual results into group level results (i.e. one row of variable results per team)
groupedProportion <- stats %>%
group_by(room, batch, round, condition, results.condition, results.format) %>%
summarise(n=n(), mean=mean(sum), median=median(sum),prop=sum(repeatTeam)/n) %>%
## Filter out all teams with n=1 (i.e. a person in a chat room alone)
filter(n>1)
## Individual proportion:
individualProportion <- stats %>% group_by(round, batch, room) %>%
mutate(sum=sum, mean=mean(sum), median=median(sum), n=n(),prop=sum(repeatTeam)/n) %>% filter(n>1)
## Table showing how many teams we've run in each condition combination:
table(groupedProportion$condition, groupedProportion$results.condition)
control treatment
A 18 37
Ap 18 37
B 19 35
Exploratory data analysis part #2:
## Plot of prop and mean per team with standard error:
ggplot(groupedProportion, aes(x=prop, y=mean)) +
geom_point() +
stat_smooth(method = "lm", col = "red") +
labs(subtitle="",
x="Proportion of answers to Q15: ",
y="Numeric sum of viability measures questions (range: 7-70)") + facet_grid(condition ~ results.format)

## Unlist for condition for graph:
groupedProportion$results.condition <- unlist(groupedProportion$results.condition)
## Team viability sum and Q15 factor repeat team answers facet_grid by condition, results.condition and results.format (all users)
g <- ggplot(stats, aes(factor(repeatTeam), sum))
g + geom_boxplot(varwidth=T, fill="plum") +
labs(subtitle="Sum of viability measures grouped by repeat team question:",
x="Distribution of responses to Q15: ",
y="Numeric sum of viability measures questions (range: 7-70)") + facet_grid(condition ~ results.format)

g <- ggplot(stats, aes(factor(repeatTeam), sum))
g + geom_boxplot(varwidth=T, fill="plum") +
labs(subtitle="Individual fracture score vs. mean viability:",
x="",
y="Numeric sum of viability measures questions (range: 7-70)") + facet_grid(condition ~ results.condition)

## groupedProportion: anlaysis on team level
ggplot(groupedProportion, aes(x=prop, y=mean)) +
geom_point() +
stat_smooth(method = "lm", col = "red") + labs(title="Team fracture proportion vs. team mean viability")

## Mean vs. median plot for viability sums per team:
ggplot(groupedProportion, aes(x=mean, y=median)) +
geom_point() +
stat_smooth(method = "lm", col = "red") + labs(main="Scatterplot of median vs. mean for team viability sums")

ggplot(data=groupedProportion, aes(groupedProportion$prop)) +
geom_histogram(breaks=seq(0, 1, by=0.20),
col="red",
fill="green",
alpha=.2) + labs(title="Count of team proportions of fracture value responses",
x="", y="Count") + facet_grid(condition ~ results.format)

Probability of fracture across teams and condition combinations:


Probability of fracture given condition in treatment:
tally(~fractureGreaterEqual50 | condition, data = conditionalPropTreatment, format = "proportion")
condition
fractureGreaterEqual50 A Ap
0 0.5405405 0.6756757
1 0.4594595 0.3243243
Boxplot for fracture scores vs. viability score sum (7-70)

Absolute change in fracture proportions between conditions:
Histogram comparisons of fracture ratios across treatment, control and learning effect conditions
ggplot(data=groupedProportionFractureTreatment, aes(fracture)) +
geom_bar(breaks=seq(0, 1, by=0.20),
col="red",
fill="green",
alpha=.2) + labs(title="Fracture ratios: treatment condition") + facet_grid(condition ~ results.condition)
Ignoring unknown parameters: breaks

ggplot(data=groupedProportionFractureControl, aes(fracture)) +
geom_bar(breaks=seq(0, 1, by=0.20),
col="red",
fill="green",
alpha=.2) + labs(title="Fracture ratios: control round") + facet_grid(condition ~ results.condition)
Ignoring unknown parameters: breaks

ggplot(data=groupedProportionFractureLE, aes(fracture)) +
geom_bar(breaks=seq(0, 1, by=0.20),
col="red",
fill="green",
alpha=.2) + labs(title="Fracture ratios: learning effect condition") + facet_grid(results.condition ~ round)
Ignoring unknown parameters: breaks

Graphs for mean distrbution per treatment condition:
## Mean viability distribution graph: treatment condition, A group
barfill <- "#4271AE"
barlines <- "#1F3552"
## Mean for treatment and A group: ##fill-in)
meanDistributionTreatmentA <- ggplot(treatmentAStats, aes(x = sum)) +
geom_histogram(aes(y = ..count..), binwidth = 5,
colour = barlines, fill = barfill) +
scale_x_continuous(name = "Median viability sum",
breaks = seq(0, 100, 20),
limits=c(0, 70)) +
scale_y_continuous(name = "count") +
ggtitle("Frequency of sum of viability scores: N=##fill-in") +
theme_bw() +
theme(axis.line = element_line(size=1, colour = "black"),
panel.grid.major = element_line(colour = "#d3d3d3"),
panel.grid.minor = element_blank(),
panel.border = element_blank(), panel.background = element_blank(),
plot.title = element_text(size = 14, family = "Tahoma", face = "bold"),
text=element_text(family="Tahoma"),
axis.text.x=element_text(colour="black", size = 9),
axis.text.y=element_text(colour="black", size = 9)) +
geom_vline(xintercept = ##fill-in, size = 1, colour = "#FF3721",
linetype = "dashed")
Error: unexpected '=' in:
" geom_vline(xintercept = ##fill-in, size = 1, colour = "#FF3721",
linetype ="
Chat data:
Conditional probabilities:
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKIyMgU2V0LXVwIHBhY2thZ2VzIC8vIGxpYnJhcmllcyBhbmQgcHJlcGFyZSBmb3IgZGF0YSBpbXBvcnQ6IApgYGB7cn0KIyMgVW5jb21tZW50IGluc3RhbGwucGFja2FnZXMgYW5kIHJ1biBvdXRzaWRlIG9mIG5vdGVib29rIGVudmlyb25tZW50OiAKIyMgaW5zdGFsbC5wYWNrYWdlcyhjKCJwc3ljaCIgLCJ4dGFibGUiLCAidGlkeXZlcnNlIiwgImpzb25saXRlIiwgImxpa2VydCIsICJnZ3Bsb3QyIiwgInBsb3R5IiwgIm1vc2FpYyIpKQoKbGlicmFyeShwc3ljaCkKbGlicmFyeShsaWtlcnQpCmxpYnJhcnkoanNvbmxpdGUpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShtb3NhaWMpCmxpYnJhcnkocGxvdGx5KQpzb3VyY2UoImh0dHA6Ly9wY3d3dy5saXYuYWMudWsvfndpbGxpYW0vUi9jcm9zc3RhYi5yIikKdGhlbWVfc2V0KHRoZW1lX2NsYXNzaWMoKSkKYGBgCgojIyBTZXQtdXAgZGlyZWN0b3JpZXMsIGltcG9ydCBhbmQgY2xlYW4gZGF0YTogCmBgYHtyfQpybShsaXN0PWxzKCkpCnNldHdkKCIvVXNlcnMvYWxsaWVibGFpc2luZy9kZXNrdG9wL2JhbmcvUiIpIApnZXR3ZCgpCmRhdGFQYXRoID0gIi4uLy5kYXRhIgojIyBEZWZpbmUgZnVuY3Rpb24gdG8gZXh0cmFjdCBzdXJ2ZXkgcmVzdWx0czogCmV4dHJhY3RTdXJ2ZXkgPSBmdW5jdGlvbihmcmFtZSxzdXJ2ZXkpIHsKICByb3VuZHMgPSBzZXEoMSxsZW5ndGgoZnJhbWUkcmVzdWx0cy5mb3JtYXRbWzFdXSkpCiAgcm91bmRSZXNwb25zZXMgPSBsYXBwbHkocm91bmRzLCBmdW5jdGlvbihyb3VuZCkgewogICAgZ2V0Q29sID0gcGFzdGUoInJlc3VsdHMuIixzdXJ2ZXksIi4iLHJvdW5kLCBzZXA9IiIpCiAgICBzdXJ2ZXlDb2xzID0gRmlsdGVyKGZ1bmN0aW9uKHgpIGdyZXBsKGdldENvbCx4KSxuYW1lcyhmcmFtZSkpCiAgICBuZXdDb2xzID0gbGFwcGx5KHN1cnZleUNvbHMsIGZ1bmN0aW9uKHgpIGdzdWIoZ2V0Q29sLHBhc3RlKCJyZXN1bHRzLiIsc3VydmV5LCBzZXA9IiIpLHgpICkKICAgIHN1cnZleUZyYW1lID0gZnJhbWVbLHN1cnZleUNvbHNdCiAgICBpZiAoaXMubnVsbChuZXdDb2xzKSkge3JldHVybigiTm8gbmV3Q29scyIpfQogICAgbmFtZXMoc3VydmV5RnJhbWUpID0gbmV3Q29scwogICAgc3VydmV5RnJhbWUkaWQgPSBmcmFtZSRpZAogICAgc3VydmV5RnJhbWUkcm91bmQgPSByb3VuZAogICAgc3VydmV5RnJhbWUkYmF0Y2ggPSBmcmFtZSRiYXRjaAogICAgc3VydmV5RnJhbWUkcm9vbXMgPSBmcmFtZSRyb29tcwogICAgc3VydmV5RnJhbWUkbWFuaXB1bGF0aW9uID0gZnJhbWUkcmVzdWx0cy5tYW5pcHVsYXRpb25DaGVjawogICAgc3VydmV5RnJhbWUkYmxhY2tsaXN0ID0gZnJhbWUkcmVzdWx0cy5ibGFja2xpc3RDaGVjawogICAgcmV0dXJuKHN1cnZleUZyYW1lKQogIH0pCiAgcmV0dXJuKFJlZHVjZShyYmluZCxyb3VuZFJlc3BvbnNlcykpCn0KI0ZpbmQgZGlyZWN0b3J5IGZvciBpbXBvcnQgKGJlIHN1cmUgdG8gdmVyaWZ5IHRoYXQgYmF0Y2ggI3MgYWxpZ24gZnJvbSBiYW5nRGF0YSBpbXBvcnQgYW5kIGltcG9ydHMgYmVsb3cpOiAKYmF0Y2hlcyA9IGRpcihkYXRhUGF0aCwgcGF0dGVybiA9ICJeWzAtOV0rJCIgKQpjb21wbGV0ZUJhdGNoZXMgPSBGaWx0ZXIoZnVuY3Rpb24oYmF0Y2gpIHsgCiAgaWYgKGFueShkaXIocGFzdGUoZGF0YVBhdGgsYmF0Y2gsc2VwPSIvIikpID09ICJiYXRjaC5qc29uIikgJiYgKGFueShkaXIocGFzdGUoZGF0YVBhdGgsYmF0Y2gsc2VwPSIvIikpID09ICJ1c2Vycy5qc29uIikpICkgewogICAgYmF0Y2hEYXRhID0gcmVhZF9qc29uKHBhc3RlKGRhdGFQYXRoLGJhdGNoLCJiYXRjaC5qc29uIixzZXA9Ii8iKSwgc2ltcGxpZnlWZWN0b3IgPSBUUlVFKQogICAgcmV0dXJuKGFueShiYXRjaERhdGEkYmF0Y2hDb21wbGV0ZSA9PSBUUlVFKSkKICB9IAogIHJldHVybihGQUxTRSkKfSwgYmF0Y2hlcykKdXNlckZpbGVzID0gbGFwcGx5KGNvbXBsZXRlQmF0Y2hlcywgZnVuY3Rpb24oYmF0Y2gpIHsKICB1c2VyRmlsZSA9IHJlYWRfanNvbihwYXN0ZShkYXRhUGF0aCxiYXRjaCwidXNlcnMuanNvbiIsc2VwPSIvIikpCiAgcHJpbnQoYmF0Y2gpCiAgcHJpbnQoY2xhc3ModXNlckZpbGUpKSAKICBwcmludCh1c2VyRmlsZSkKICByZXR1cm4oZmxhdHRlbih1c2VyRmlsZSwgcmVjdXJzaXZlID0gVFJVRSkpCn0pCgojIyBSZXRyb2FjdGl2ZWx5IGZpbmQgcm9vbXMgZnJvbSBjaGF0IGRhdGE6IApvdmVybGFwcGluZ0ZpbGVzID0gUmVkdWNlKGZ1bmN0aW9uKHgseSkgbWVyZ2UoeCwgeSwgYWxsPVRSVUUpLCB1c2VyRmlsZXMpCnJvdW5kc1dpdGhSb29tcyA9IGFwcGx5KG92ZXJsYXBwaW5nRmlsZXMsMSxmdW5jdGlvbih4KSB7CiAgcm9vbXNGb3JJbmRpdmlkdWFsID0gbGFwcGx5KHNlcSgxLDMpLGZ1bmN0aW9uKHkpIHsKICAgIHgkcm9vbSA9IHgkcm9vbXNbeV0KICAgIHgkcm91bmQgPSB5CiAgICByZXR1cm4oeCkKICB9KQogIHJldHVybihSZWR1Y2UocmJpbmQscm9vbXNGb3JJbmRpdmlkdWFsKSkKICAKfSkKCmxpYnJhcnkodGlkeXZlcnNlKQpgYGAKCiMjIE1vcmUgY2xlYW5pbmcgYmVmb3JlIHZpc3VhbGl6YXRpb25zOiAKYGBge3J9CiMjIEFwcGx5IGV4dHJhY3Qgc3VydmV5IGZ1bmN0aW9uIHRvIGV4dHJhY3QgdGhlIHJpZ2h0IGNvbHVtbnMgYW5kIHJvd3MgZm9yIHZpYWJpbGl0eSBzdXJ2ZXk6IApzdXJ2ZXkgPSAndmlhYmlsaXR5Q2hlY2snCmZyYW1lIDwtIGV4dHJhY3RTdXJ2ZXkob3ZlcmxhcHBpbmdGaWxlcywgc3VydmV5KQojIyBSZWR1Y2UgdG8gdmVydGljYWxseSBjb21iaW5lIHJvd3MgaW4gcm91bmR3aXRoUm9vbXMgbGlzdDogIApmaW5hbFJvdW5kcyA9IGFzLmRhdGEuZnJhbWUoUmVkdWNlKHJiaW5kLHJvdW5kc1dpdGhSb29tcykpCiMjIFN1YnNldCBpbmNvbXBsZXRlIGNhc2VzIGZyb20gdmlhYmlsaXR5IHN1cnZleSBkYXRhZnJhbWU6IAojIyBNU0I6IGNvbXBsZXRlLmNhc2VzIGRvZXNuJ3Qgd29yayB3aGVuIHRoZXJlIGFyZW4ndCBOQXMsIGJ1dCBlbXB0eSBsaXN0cywgYWx0ZXJuYXRpdmVzIHJhdGhlciB0aGFuIHN1YnNldHRpbmcgd2hlcmUgCiMjIGJsYWNrbGlzdCBpcyBlbXB0eT8gRG9lbnMndCB3b3JrOiB0ZXN0IDwtIGNvbXBsZXRlLmNhc2VzKGRhdGEpCmRhdGEgPC0gZnJhbWVbZnJhbWUkbWFuaXB1bGF0aW9uIT0iIixdCiMjIFJlbmFtZSByb29tIHRvIHJvb21zIHNvIHRoYXQgYm90aCBhcmUgcmV0YWluZWQgaW4gZnV0dXJlIG1lcmdlOiAKZGF0YSA8LSByZW5hbWUoZGF0YSwgcm9vbXMgPSAicm9vbXMiKQojIyBTdWJzZXQgaW5jb21wbGV0ZSBjYXNlcyBmb3IgZmluYWwgcm91bmRzIGRhdGFmcmFtZTogCmRhdGEyIDwtIGZpbmFsUm91bmRzW2ZpbmFsUm91bmRzJHJlc3VsdHMubWFuaXB1bGF0aW9uQ2hlY2shPSIiLCBdCiMjIFNlbGVjdCBvbmx5IHZhcmlhYmxlcyBvZiBpbnRlcmVzdCBmcm9tIGZpbmFsIHJvdW5kczogCmRhdGEyID0gZGF0YTIgJT4lIHNlbGVjdChpZCwgYmF0Y2gsIHJvb20sIGJvbnVzLCBuYW1lLCBmcmllbmRzLCAKICAgICAgICAgICAgICAgICAgICAgICAgIGZyaWVuZHNfaGlzdG9yeSwgcmVzdWx0cy5jb25kaXRpb24sIHJlc3VsdHMuZm9ybWF0LAogICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0cy5tYW5pcHVsYXRpb24scmVzdWx0cy5tYW5pcHVsYXRpb25DaGVjayxyZXN1bHRzLmJsYWNrbGlzdENoZWNrLCByb3VuZCkKIyMgQ29udmVydCB0byBjb21wYXRpYmxlIGRhdGEgdHlwZXMgYmVmb3JlIG1lcmdlICh0aGlzIHNob3VsZCBiZSBzaW1wbGlmaWVkKQpkYXRhMiRiYXRjaCA8LSB1bmxpc3QoZGF0YTIkYmF0Y2gpCmRhdGEkYmF0Y2ggPC0gdW5saXN0KGRhdGEkYmF0Y2gpCmRhdGEyJHJvdW5kIDwtIHVubGlzdChkYXRhMiRyb3VuZCkKZGF0YTIkaWQgPC0gdW5saXN0KGRhdGEyJGlkKQojIyBCZWZvcmUgbWVyZ2UsIGRhdGEgYW5kIGRhdGEyIHNob3VsZCBhaHZlIHRoZSBzYW1lICMgb2Ygb2JzZXJ2YXRpb25zCiMjIE1lcmdlIGNvbHVtbnMgYnkgaWQsIHJvdW5kIGFuZCBiYXRjaCAjczogCmRhdGEgPC0gbGVmdF9qb2luKGRhdGEsIGRhdGEyLCBieT1OVUxMKQojIyBTdWJzZXQgb25seSBvYnNlcnZhdGlvbnMgd2l0aCBiYXRjaCAjcyBpbiBjb21wbGV0ZSBiYXRjaGVzIAphbGxDb25kaXRpb25zIDwtIGRhdGFbZGF0YSRiYXRjaCAlaW4lIGNvbXBsZXRlQmF0Y2hlcywgXQpgYGAKIyMgQ29uZGl0aW9uYWxseSBhc3NpZ24gY29uZGl0aW9ucyBiYXNlZCBvbiB0cmVhdG1lbnQgYW5kIHJlc3VsdHMgY29sdW1uOiAKYGBge3J9CiMjIE1lc3N5LCBidXQgcm9idXN0PyBWZXJpZnksIHZlcmlmeSwgdmVyaWZ5LiAgCmRhdGEgPC0gZGF0YSAlPiUgbXV0YXRlKAogIGNvbmRpdGlvbiA9IGNhc2Vfd2hlbigKICAgIHJlc3VsdHMuY29uZGl0aW9uPT0ndHJlYXRtZW50JyAmIHJlc3VsdHMuZm9ybWF0PT0iYygxLCAyLCAxKSIgJiByb3VuZD09MSB+ICJBIiwgCiAgICByZXN1bHRzLmNvbmRpdGlvbj09J3RyZWF0bWVudCcgJiByZXN1bHRzLmZvcm1hdD09ImMoMSwgMiwgMSkiICYgcm91bmQ9PTIgfiAiQiIsIAogICAgcmVzdWx0cy5jb25kaXRpb249PSd0cmVhdG1lbnQnICYgcmVzdWx0cy5mb3JtYXQ9PSJjKDEsIDIsIDEpIiAmIHJvdW5kPT0zIH4gIkFwIiwgCiAgICByZXN1bHRzLmNvbmRpdGlvbj09J3RyZWF0bWVudCcgJiByZXN1bHRzLmZvcm1hdD09ImMoMSwgMSwgMikiICYgcm91bmQ9PTEgfiAiQSIsIAogICAgcmVzdWx0cy5jb25kaXRpb249PSd0cmVhdG1lbnQnICYgcmVzdWx0cy5mb3JtYXQ9PSJjKDEsIDEsIDIpIiAmIHJvdW5kPT0yIH4gIkFwIiwgCiAgICByZXN1bHRzLmNvbmRpdGlvbj09J3RyZWF0bWVudCcgJiByZXN1bHRzLmZvcm1hdD09ImMoMSwgMSwgMikiICYgcm91bmQ9PTMgfiAiQiIsIAogICAgcmVzdWx0cy5jb25kaXRpb249PSd0cmVhdG1lbnQnICYgcmVzdWx0cy5mb3JtYXQ9PSJjKDIsIDEsIDEpIiAmIHJvdW5kPT0xIH4gIkIiLCAKICAgIHJlc3VsdHMuY29uZGl0aW9uPT0ndHJlYXRtZW50JyAmIHJlc3VsdHMuZm9ybWF0PT0iYygyLCAxLCAxKSIgJiByb3VuZD09MiB+ICJBIiwgCiAgICByZXN1bHRzLmNvbmRpdGlvbj09J3RyZWF0bWVudCcgJiByZXN1bHRzLmZvcm1hdD09ImMoMiwgMSwgMSkiICYgcm91bmQ9PTMgfiAiQXAiICwKICAgIHJlc3VsdHMuY29uZGl0aW9uPT0nY29udHJvbCcgJiByZXN1bHRzLmZvcm1hdD09ImMoMSwgMiwgMSkiICYgcm91bmQ9PTEgfiAiQSIsIAogICAgcmVzdWx0cy5jb25kaXRpb249PSdjb250cm9sJyAmIHJlc3VsdHMuZm9ybWF0PT0iYygxLCAyLCAxKSIgJiByb3VuZD09MiB+ICJCIiwgCiAgICByZXN1bHRzLmNvbmRpdGlvbj09J2NvbnRyb2wnICYgcmVzdWx0cy5mb3JtYXQ9PSJjKDEsIDIsIDEpIiAmIHJvdW5kPT0zIH4gIkFwIiwgCiAgICByZXN1bHRzLmNvbmRpdGlvbj09J2NvbnRyb2wnICYgcmVzdWx0cy5mb3JtYXQ9PSJjKDEsIDEsIDIpIiAmIHJvdW5kPT0xIH4gIkEiLCAKICAgIHJlc3VsdHMuY29uZGl0aW9uPT0nY29udHJvbCcgJiByZXN1bHRzLmZvcm1hdD09ImMoMSwgMSwgMikiICYgcm91bmQ9PTIgfiAiQXAiLCAKICAgIHJlc3VsdHMuY29uZGl0aW9uPT0nY29udHJvbCcgJiByZXN1bHRzLmZvcm1hdD09ImMoMSwgMSwgMikiICYgcm91bmQ9PTMgfiAiQiIsIAogICAgcmVzdWx0cy5jb25kaXRpb249PSdjb250cm9sJyAmIHJlc3VsdHMuZm9ybWF0PT0iYygyLCAxLCAxKSIgJiByb3VuZD09MSB+ICJCIiwgCiAgICByZXN1bHRzLmNvbmRpdGlvbj09J2NvbnRyb2wnICYgcmVzdWx0cy5mb3JtYXQ9PSJjKDIsIDEsIDEpIiAmIHJvdW5kPT0yIH4gIkEiLCAKICAgIHJlc3VsdHMuY29uZGl0aW9uPT0nY29udHJvbCcgJiByZXN1bHRzLmZvcm1hdD09ImMoMiwgMSwgMSkiICYgcm91bmQ9PTMgfiAiQXAiICwgCiAgICByZXN1bHRzLmNvbmRpdGlvbj09J2Jhc2VsaW5lJyAmIHJlc3VsdHMuZm9ybWF0PT0iYygxLCAyLCAzKSIgJiByb3VuZD09MSB+ICJBIiAsCiAgICByZXN1bHRzLmNvbmRpdGlvbj09J2Jhc2VsaW5lJyAmIHJlc3VsdHMuZm9ybWF0PT0iYygxLCAyLCAzKSIgJiByb3VuZD09MiB+ICJCIiAsCiAgICByZXN1bHRzLmNvbmRpdGlvbj09J2Jhc2VsaW5lJyAmIHJlc3VsdHMuZm9ybWF0PT0iYygxLCAyLCAzKSIgJiByb3VuZD09MyB+ICJDIiAKICApKSAKYGBgCgojIyBTZXQtdXAgZm9yIGZhY3RvcnMgZm9yIHZpYWJpbGl0eSBxdWVzdGlvbnM6IApgYGB7cn0KZGF0YSA8LSByZW5hbWUoZGF0YSwgInJlcGVhdFRlYW0iID0gcmVzdWx0cy52aWFiaWxpdHlDaGVjay4xNSkKIyMgUmVtb3ZlIG9ic2VydmF0aW9ucyB3aGVyZSB2aWFiaWxpdHkgc3VydmV5IHdhc24ndCBvbiAocmVtb3ZlIHRoaXMgbGluZSBpZiB3ZSB3YW50IHRvIGtlZXAgb2JzZXJ2YXRpb25zIHdpdGggdmlhYmlsaXR5IG9mZik6IApkYXRhIDwtIG5hLm9taXQoZGF0YSkKbGV2ZWxzIDwtIGMoIlN0cm9uZ2x5IERpc2FncmVlIiwgIkRpc2FncmVlIiwgIk5ldXRyYWwiLCJBZ3JlZSIsICJTdHJvbmdseSBBZ3JlZSIpIApjbGVhbiA8LSBkYXRhICU+JSAKICBtdXRhdGVfYXQoLnZhcnMgPSB2YXJzKGNvbnRhaW5zKCJyZXN1bHRzLnZpYWJpbGl0eUNoZWNrIikpLCBmdW5zKGZhY3RvciguLCBsZXZlbHMgPSBsZXZlbHMpKSkgCiMjIFZpYWJpbGl0eWxpa2VydCB2aXN1YWxzOiAKIyMgU3Vic2V0IG9ubHkgdmlhYmlsaXR5U3VydmV5IGNvbHVtbnMgYW5kIGNvbmRpdGlvbiBjb2x1bW4gKGNvbmRpdGlvbiBjb2x1bW4gdXNlZCB0byB2aXN1YWxpemUgbGlrZXJ0IHJlc3BvbnNlcyBmb3IgY29uZGl0aW9ucykKdmlhYmlsaXR5TGlrZXJ0IDwtIHNlbGVjdChjbGVhbiwgY29udGFpbnMoInJlc3VsdHMudmlhYmlsaXR5Q2hlY2siKSwgImNvbmRpdGlvbiIsICJyZXN1bHRzLmNvbmRpdGlvbiIpCnZpYWJpbGl0eUxhYmVscyA9IGMoIjEuIFRoZSBtZW1iZXJzIG9mIHRoaXMgdGVhbSBjb3VsZCB3b3JrIGZvciBhIGxvbmcgdGltZSB0b2dldGhlciIgCiAgICAgICAgICAgICAgICAgICAgLCAiMi4gTW9zdCBvZiB0aGUgbWVtYmVycyBvZiB0aGlzIHRlYW0gd291bGQgd2VsY29tZSB0aGUgb3Bwb3J0dW5pdHkgdG8gd29yayBhcyBhIGdyb3VwIGFnYWluIGluIHRoZSBmdXR1cmUuIiAsIAogICAgICAgICAgICAgICAgICAgICIzLiBUaGlzIHRlYW0gaGFzIHRoZSBjYXBhY2l0eSBmb3IgbG9uZy10ZXJtIHN1Y2Nlc3MuIiwgCiAgICAgICAgICAgICAgICAgICAgIjQuIFRoaXMgdGVhbSBoYXMgd2hhdCBpdCB0YWtlcyB0byBiZSBlZmZlY3RpdmUgaW4gdGhlIGZ1dHVyZS4iLCAKICAgICAgICAgICAgICAgICAgICAiNS4gVGhpcyB0ZWFtIHdvdWxkIHdvcmsgd2VsbCB0b2dldGhlciBpbiB0aGUgZnV0dXJlLiIgLCAKICAgICAgICAgICAgICAgICAgICAiIDYuIFRoaXMgdGVhbSBoYXMgcG9zaXRpb25lZCBpdHNlbGYgd2VsbCBmb3IgY29udGludWVkIHN1Y2Nlc3MuIiwgIAogICAgICAgICAgICAgICAgICAgICIgNy4gVGhpcyB0ZWFtIGhhcyB0aGUgYWJpbGl0eSB0byBwZXJmb3JtIHdlbGwgaW4gdGhlIGZ1dHVyZS4gIiwgCiAgICAgICAgICAgICAgICAgICAgIiA4LiBUaGlzIHRlYW0gaGFzIHRoZSBhYmlsaXR5IHRvIGZ1bmN0aW9uIGFzIGFuIG9uZ29pbmcgdW5pdC4iICwgCiAgICAgICAgICAgICAgICAgICAgIiA5LiBUaGlzIHRlYW0gc2hvdWxkIGNvbnRpbnVlIHRvIGZ1bmN0aW9uIGFzIGEgdW5pdC4gIiwgCiAgICAgICAgICAgICAgICAgICAgIiAxMC4gVGhpcyB0ZWFtIGhhcyB0aGUgcmVzb3VyY2VzIHRvIHBlcmZvcm0gd2VsbCBpbiB0aGUgZnV0dXJlLiAiLCAKICAgICAgICAgICAgICAgICAgICAiIDExLiBUaGlzIHRlYW0gaXMgd2VsbCBwb3NpdGlvbmVkIGZvciBncm93dGggb3ZlciB0aW1lLiAiLCAKICAgICAgICAgICAgICAgICAgICAiIDEyLiBUaGlzIHRlYW0gY2FuIGRldmVsb3AgdG8gbWVldCBmdXR1cmUgY2hhbGxlbmdlcy4gIiwgCiAgICAgICAgICAgICAgICAgICAgIiAxMy4gVGhpcyB0ZWFtIGhhcyB0aGUgY2FwYWNpdHkgdG8gc3VzdGFpbiBpdHNlbGYuICIsIAogICAgICAgICAgICAgICAgICAgICIgMTQuIFRoaXMgdGVhbSBoYXMgd2hhdCBpdCB0YWtlcyB0byBlbmR1cmUgaW4gZnV0dXJlIHBlcmZvcm1hbmNlIGVwaXNvZGVzLiIsICJjb25kaXRpb24iLCAicmVzdWx0cy5jb25kaXRpb24iKSAKbmFtZXModmlhYmlsaXR5TGlrZXJ0KSA8LSByZXAodmlhYmlsaXR5TGFiZWxzKSAKYGBgCgojIyBMaWtlcnQgdmlzdWFsaXphdGlvbnM6IApgYGB7cn0KIyMgTGlrZXJ0IGdyYXBoIGZvciBhbGwgdmlhYmlsaXR5IHJlc3BvbnNlcyBhY3Jvc3MgYWxsIGNvbmRpdGlvbnMgKGkuZS4gYmFzZWxpbmUsIGNvbnRyb2wgYW5kIHRyZWF0bWVudCk6IApsaWtlcnQub3V0IDwtIGxpa2VydCh2aWFiaWxpdHlMaWtlcnRbLWMoMTU6MTYpXSkgCnBsb3QobGlrZXJ0Lm91dCkKIyMgU3Vic2V0IEEgYW5kIEFwIChpLmUuIEEgcHJpbWUpIHJlc3BvbnNlcyBmb3IgdHJlYXRtZW50IGdyb3VwOiAKIyBUcmVhdG1lbnQgKyBBOiAKdHJlYXRtZW50QSA8LSB2aWFiaWxpdHlMaWtlcnQgJT4lIGZpbHRlcihjb25kaXRpb249PSJBIiAmIHJlc3VsdHMuY29uZGl0aW9uPT0idHJlYXRtZW50IikgCmxpa2VydC50cmVhdG1lbnRBIDwtIGxpa2VydCh0cmVhdG1lbnRBWy1jKDE1OjE2KV0pCnBsb3QobGlrZXJ0LnRyZWF0bWVudEEpCiMgVHJlYXRtZW50ICsgQXA6IAp0cmVhdG1lbnRBcCA8LSB2aWFiaWxpdHlMaWtlcnQgJT4lIGZpbHRlcihjb25kaXRpb249PSJBcCIgJiByZXN1bHRzLmNvbmRpdGlvbj09InRyZWF0bWVudCIpIApsaWtlcnQudHJlYXRtZW50QXAgPC0gbGlrZXJ0KHRyZWF0bWVudEFwWy1jKDE1OjE2KV0pCnBsb3QobGlrZXJ0LnRyZWF0bWVudEFwKQojIFRyZWF0bWVudCArIEI6IAp0cmVhdG1lbnRCIDwtIHZpYWJpbGl0eUxpa2VydCAlPiUgZmlsdGVyKGNvbmRpdGlvbj09IkIiICYgcmVzdWx0cy5jb25kaXRpb249PSJ0cmVhdG1lbnQiKSAKbGlrZXJ0LnRyZWF0bWVudEIgPC0gbGlrZXJ0KHRyZWF0bWVudEJbLWMoMTU6MTYpXSkKcGxvdChsaWtlcnQudHJlYXRtZW50QXApCiMjIEN1c3RvbWl6ZSBjb2RlIGFib3ZlIHRvIGZpbHRlciBvbiBvdGhlciBjb25kaXRpb25zIGFuZCB0cmVhdG1lbnRzIG9mIGludGVyZXN0LiAKYGBgCgojIyBFeHBsb3JhdG9yeSBkYXRhIGFuYWx5c2lzIHBhcnQgIzE6IApgYGB7cn0KIyMgQ3JlYXRlIGEgbmV3IGRhdGFmcmFtZSB0aGF0IGNvbnZlcnRzIGZhY3RvcnMgdG8gbnVtZXJpYyBmb3Igc3RhdGlzdGljYWwgYW5hbHlzZXM6IApzdGF0cyA8LSBjbGVhbiAlPiUgbXV0YXRlX2lmKGlzLmZhY3RvciwgYXMubnVtZXJpYykKZm9yIChpIGluIDE6bnJvdyhzdGF0cykpIHsKICBzdGF0cyRzdW1baV0gPC0gc3VtKHN0YXRzW2ksMToxNF0pICAgICAgICAgICAgICAgICAgICAgICAgICAKfSAKc3RhdHMkbWVkaWFuIDwtIG1lZGlhbihzdGF0cyRzdW0pCnN0YXRzJG1lYW4gPC0gbWVhbihzdGF0cyRzdW0pCiMjIFJldmFsdWUgcmVwZWF0IHRlYW06IGtlZXAgcGx5ciBiL2Mgc29tZSB3ZWlyZCBSIHN0dWZmIHJlcXVpcmVzIGxpYnJhcnkgdG8gYmUgY2FsbGVkIGRpcmVjdGx5IChyZWNvZGUgdmFsdWVzIHRvICkKc3RhdHMkcmVwZWF0VGVhbSA8LSBwbHlyOjpyZXZhbHVlKHN0YXRzJHJlcGVhdFRlYW0sIGMoIlllcyI9IjAiLCAiTm8iPSIxIikpCnN0YXRzJHJlcGVhdFRlYW0gPC0gcGx5cjo6cmV2YWx1ZShzdGF0cyRyZXBlYXRUZWFtLCBjKCJLZWVwIHRoaXMgdGVhbSI9IjAiLCAiRG8gbm90IGtlZXAgdGhpcyB0ZWFtIj0iMSIpKQojIyBDb252ZXJ0IHRvIGNvbXBhdGlibGUgY2xhc3NlcyBmb3IgdGVhbSBncm91cGluZzogCnN0YXRzJHJlcGVhdFRlYW0gPC0gYXMubnVtZXJpYyhzdGF0cyRyZXBlYXRUZWFtKQpzdGF0cyRyZXN1bHRzLmNvbmRpdGlvbiA8LSB1bmxpc3Qoc3RhdHMkcmVzdWx0cy5jb25kaXRpb24pCnN0YXRzJHJlc3VsdHMuZm9ybWF0IDwtIGFzLmNoYXJhY3RlcihzdGF0cyRyZXN1bHRzLmZvcm1hdCkKc3RhdHMkcm9vbSA8LSB1bmxpc3Qoc3RhdHMkcm9vbSkKIyMgRHBseXIgdG8gZ3JvdXAgdGVhbXMgYW5kIHN1bW1hcmlzZSB2YXJpYWJsZXMgZm9yIGVhY2ggZ3JvdXA6IGdyb3VwX2J5IHRvIGZpbmQgdGVhbXMgYW5kIHN1bW1hcmlzZSB0byBjb21wYWN0IGluZGl2aWR1YWwgcmVzdWx0cyBpbnRvIGdyb3VwIGxldmVsIHJlc3VsdHMgKGkuZS4gb25lIHJvdyBvZiB2YXJpYWJsZSByZXN1bHRzIHBlciB0ZWFtKQpncm91cGVkUHJvcG9ydGlvbiA8LSBzdGF0cyAlPiUKICBncm91cF9ieShyb29tLCBiYXRjaCwgcm91bmQsIGNvbmRpdGlvbiwgcmVzdWx0cy5jb25kaXRpb24sIHJlc3VsdHMuZm9ybWF0KSAlPiUgCiAgc3VtbWFyaXNlKG49bigpLCBtZWFuPW1lYW4oc3VtKSwgbWVkaWFuPW1lZGlhbihzdW0pLHByb3A9c3VtKHJlcGVhdFRlYW0pL24pICU+JSAKIyMgRmlsdGVyIG91dCBhbGwgdGVhbXMgd2l0aCBuPTEgKGkuZS4gYSBwZXJzb24gaW4gYSBjaGF0IHJvb20gYWxvbmUpCiAgZmlsdGVyKG4+MikKIyMgSW5kaXZpZHVhbCBwcm9wb3J0aW9uOiAKaW5kaXZpZHVhbFByb3BvcnRpb24gPC0gc3RhdHMgJT4lIGdyb3VwX2J5KHJvdW5kLCBiYXRjaCwgcm9vbSkgJT4lIAogIG11dGF0ZShzdW09c3VtLCBtZWFuPW1lYW4oc3VtKSwgbWVkaWFuPW1lZGlhbihzdW0pLCBuPW4oKSxwcm9wPXN1bShyZXBlYXRUZWFtKS9uKSAlPiUgZmlsdGVyKG4+MSkKCiMjIFRhYmxlIHNob3dpbmcgaG93IG1hbnkgdGVhbXMgd2UndmUgcnVuIGluIGVhY2ggY29uZGl0aW9uIGNvbWJpbmF0aW9uOiAgCnRhYmxlKGdyb3VwZWRQcm9wb3J0aW9uJGNvbmRpdGlvbiwgZ3JvdXBlZFByb3BvcnRpb24kcmVzdWx0cy5jb25kaXRpb24pCmBgYAoKIyMgRXhwbG9yYXRvcnkgZGF0YSBhbmFseXNpcyBwYXJ0ICMyOiAKYGBge3J9CiMjIFBsb3Qgb2YgcHJvcCBhbmQgbWVhbiBwZXIgdGVhbSB3aXRoIHN0YW5kYXJkIGVycm9yOiAKZ2dwbG90KGdyb3VwZWRQcm9wb3J0aW9uLCBhZXMoeD1wcm9wLCB5PW1lYW4pKSArIAogIGdlb21fcG9pbnQoKSArCiAgc3RhdF9zbW9vdGgobWV0aG9kID0gImxtIiwgY29sID0gInJlZCIpICsgCiAgbGFicyhzdWJ0aXRsZT0iIiwgCiAgICAgICB4PSJQcm9wb3J0aW9uIG9mIGFuc3dlcnMgdG8gUTE1OiAiLAogICAgICAgeT0iTnVtZXJpYyBzdW0gb2YgdmlhYmlsaXR5IG1lYXN1cmVzIHF1ZXN0aW9ucyAocmFuZ2U6IDctNzApIikgKyBmYWNldF9ncmlkKGNvbmRpdGlvbiB+IHJlc3VsdHMuZm9ybWF0KQoKIyMgVW5saXN0IGZvciBjb25kaXRpb24gZm9yIGdyYXBoOiAKZ3JvdXBlZFByb3BvcnRpb24kcmVzdWx0cy5jb25kaXRpb24gPC0gdW5saXN0KGdyb3VwZWRQcm9wb3J0aW9uJHJlc3VsdHMuY29uZGl0aW9uKQojIyBUZWFtIHZpYWJpbGl0eSBzdW0gYW5kIFExNSBmYWN0b3IgcmVwZWF0IHRlYW0gYW5zd2VycyBmYWNldF9ncmlkIGJ5IGNvbmRpdGlvbiwgcmVzdWx0cy5jb25kaXRpb24gYW5kIHJlc3VsdHMuZm9ybWF0IChhbGwgdXNlcnMpIApnIDwtIGdncGxvdChzdGF0cywgYWVzKGZhY3RvcihyZXBlYXRUZWFtKSwgc3VtKSkKZyArIGdlb21fYm94cGxvdCh2YXJ3aWR0aD1ULCBmaWxsPSJwbHVtIikgKyAKICBsYWJzKHN1YnRpdGxlPSJTdW0gb2YgdmlhYmlsaXR5IG1lYXN1cmVzIGdyb3VwZWQgYnkgdGVhbSBmcmFjdHVyZSB2YWx1ZSIsIAogICAgICAgeD0iQmluYXJ5IGZyYWN0dXJlIHZhbHVlIiwKICAgICAgIHk9Ik51bWVyaWMgc3VtIG9mIHZpYWJpbGl0eSBtZWFzdXJlcyBxdWVzdGlvbnMgKHJhbmdlOiA3LTcwKSIpICsgZmFjZXRfZ3JpZChjb25kaXRpb24gfiByZXN1bHRzLmZvcm1hdCkKCmcgPC0gZ2dwbG90KHN0YXRzLCBhZXMoZmFjdG9yKHJlcGVhdFRlYW0pLCBzdW0pKQpnICsgZ2VvbV9ib3hwbG90KHZhcndpZHRoPVQsIGZpbGw9InBsdW0iKSArIAogIGxhYnMoc3VidGl0bGU9IkluZGl2aWR1YWwgZnJhY3R1cmUgc2NvcmUgdnMuIG1lYW4gdmlhYmlsaXR5OiIsIAogICAgICAgeD0iIiwKICAgICAgIHk9Ik51bWVyaWMgc3VtIG9mIHZpYWJpbGl0eSBtZWFzdXJlcyBxdWVzdGlvbnMgKHJhbmdlOiA3LTcwKSIpICsgZmFjZXRfZ3JpZChjb25kaXRpb24gfiByZXN1bHRzLmNvbmRpdGlvbikKCiMjIGdyb3VwZWRQcm9wb3J0aW9uOiBhbmxheXNpcyBvbiB0ZWFtIGxldmVsIAoKZ2dwbG90KGdyb3VwZWRQcm9wb3J0aW9uLCBhZXMoeD1wcm9wLCB5PW1lYW4pKSArIAogIGdlb21fcG9pbnQoKSArCiAgc3RhdF9zbW9vdGgobWV0aG9kID0gImxtIiwgY29sID0gInJlZCIpICsgbGFicyh0aXRsZT0iVGVhbSBmcmFjdHVyZSBwcm9wb3J0aW9uIHZzLiB0ZWFtIG1lYW4gdmlhYmlsaXR5IikgCgojIyBNZWFuIHZzLiBtZWRpYW4gcGxvdCBmb3IgdmlhYmlsaXR5IHN1bXMgcGVyIHRlYW06IApnZ3Bsb3QoZ3JvdXBlZFByb3BvcnRpb24sIGFlcyh4PW1lYW4sIHk9bWVkaWFuKSkgKyAKICBnZW9tX3BvaW50KCkgKwogIHN0YXRfc21vb3RoKG1ldGhvZCA9ICJsbSIsIGNvbCA9ICJyZWQiKSArIGxhYnMobWFpbj0iU2NhdHRlcnBsb3Qgb2YgbWVkaWFuIHZzLiBtZWFuIGZvciB0ZWFtIHZpYWJpbGl0eSBzdW1zIikKCmdncGxvdChkYXRhPWdyb3VwZWRQcm9wb3J0aW9uLCBhZXMoZ3JvdXBlZFByb3BvcnRpb24kcHJvcCkpICsgCiAgZ2VvbV9oaXN0b2dyYW0oYnJlYWtzPXNlcSgwLCAxLCBieT0wLjIwKSwgCiAgICAgICAgICAgICAgICAgY29sPSJyZWQiLCAKICAgICAgICAgICAgICAgICBmaWxsPSJncmVlbiIsIAogICAgICAgICAgICAgICAgIGFscGhhPS4yKSArIGxhYnModGl0bGU9IkNvdW50IG9mIHRlYW0gcHJvcG9ydGlvbnMgb2YgZnJhY3R1cmUgdmFsdWUgcmVzcG9uc2VzIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB4PSIiLCB5PSJDb3VudCIpICsgZmFjZXRfZ3JpZChjb25kaXRpb24gfiByZXN1bHRzLmZvcm1hdCkKCmBgYAoKIyMgUHJvYmFiaWxpdHkgb2YgZnJhY3R1cmUgYWNyb3NzIHRlYW1zIGFuZCBjb25kaXRpb24gY29tYmluYXRpb25zOiAKYGBge3J9CiMjIERlZmluZSBhbmQgaW5pdGlhbGl6ZSBjdXQtb2ZmIHBvaW50IGZvciBmcmFjdHVyZTogCmdyb3VwZWRQcm9wb3J0aW9uRnJhY3R1cmUgPC0gZ3JvdXBlZFByb3BvcnRpb24gJT4lCiAgZ3JvdXBfYnkocmVzdWx0cy5jb25kaXRpb24sIGNvbmRpdGlvbikgJT4lIAogIG11dGF0ZShmcmFjdHVyZUdyZWF0ZXI1MCA9IGNhc2Vfd2hlbiAocHJvcDw9LjUwIH4gIjAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wPi41MH4gIjEiKSwgCiAgICAgICAgIGZyYWN0dXJlR3JlYXRlckVxdWFsNTAgPSBjYXNlX3doZW4gKHByb3A8LjUwIH4gIjAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wPj0uNTAgfiAiMSIpKQoKIyMgRnJhY3R1cmUgcHJvcG9ydGlvbiBzY2F0dGVycGxvdHM6IAojIyBMZWFybmluZyBlZmZlY3QgLy8gYmFzZWxpbmU6IAojIyBNYWtlIG5ldyBkYXRhIHRoYXQgaW5jbHVkZXMgdGVhbXMgd2l0aCBkaWZmZXJlbnQgcm91bmQgMSBhbmQgcm91bmQgMyB0ZWFtczogCmdyb3VwZWRQcm9wb3J0aW9uRnJhY3R1cmVMRSA8LSBncm91cGVkUHJvcG9ydGlvbkZyYWN0dXJlICU+JSBmaWx0ZXIocmVzdWx0cy5mb3JtYXQ9PSJjKDEsIDEsIDIpIiB8IHJlc3VsdHMuZm9ybWF0PT0iYygyLCAxLCAxKSIgJiByb3VuZD09IjEiIHwgcm91bmQ9PSIzIikgCmZyYWN0dXJlTEUxIDwtIGdyb3VwZWRQcm9wb3J0aW9uRnJhY3R1cmVMRSAlPiUgZmlsdGVyKHJvdW5kPT0iMSIpCmZyYWN0dXJlTEUyIDwtIGdyb3VwZWRQcm9wb3J0aW9uRnJhY3R1cmVMRSAlPiUgZmlsdGVyKHJvdW5kPT0iMyIpCgojIyBUcmVhdG1lbnQ6IApncm91cGVkUHJvcG9ydGlvbkZyYWN0dXJlVHJlYXRtZW50IDwtIGdyb3VwZWRQcm9wb3J0aW9uRnJhY3R1cmUgJT4lIApmaWx0ZXIocmVzdWx0cy5jb25kaXRpb249PSJ0cmVhdG1lbnQiKQp0cmVhdG1lbnRGcmFjdHVyZTEgPC0gZ3JvdXBlZFByb3BvcnRpb25GcmFjdHVyZVRyZWF0bWVudCAlPiUgZmlsdGVyKGNvbmRpdGlvbj09IkEiKQp0cmVhdG1lbnRGcmFjdHVyZTIgPC0gZ3JvdXBlZFByb3BvcnRpb25GcmFjdHVyZVRyZWF0bWVudCAlPiUgZmlsdGVyKGNvbmRpdGlvbj09IkFwIikKdHJlYXRtZW50RnJhY3R1cmUgPC0gY2JpbmQodHJlYXRtZW50RnJhY3R1cmUxLCB0cmVhdG1lbnRGcmFjdHVyZTIpCgpnZ3Bsb3QodHJlYXRtZW50RnJhY3R1cmUsIGFlcyhwcm9wLCBwcm9wMSkpICsKICBnZW9tX3BvaW50KCkgKwogIGdlb21faml0dGVyKCkgKyBjb29yZF9maXhlZCgpICsgeGxpbSgwLjAsMS4wKSArIHlsaW0oMC4wLDEuMCkgKyBsYWJzKHRpdGxlPSJQcm9wb3J0aW9uIG9mIHRlYW0gZnJhY3R1cmUgaW4gdGhlIGZpcnN0IHZzLiB0aGlyZCBpbiB0cmVhdG1lbnQiLCBzdWJ0aXRsZT0iTm8gZnJhY3R1cmU9MCwgRnJhY3R1cmU9MSIsICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB4PSJGcmFjdHVyZSB0aGUgZmlyc3QgdGltZSBhIHRlYW0gaW50ZXJhY3RzIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeT0iRnJhY3R1cmUgdGhlIHNlY29uZCB0aW1lIGEgdGVhbSBpbnRlcmFjdHMsIHdpdGhvdXQga25vd2luZyBpdCIpIAoKIyMgQ29udHJvbDogIApncm91cGVkUHJvcG9ydGlvbkZyYWN0dXJlQ29udHJvbCA8LSBncm91cGVkUHJvcG9ydGlvbkZyYWN0dXJlICU+JSAKICBmaWx0ZXIocmVzdWx0cy5jb25kaXRpb249PSJjb250cm9sIikgCmNvbnRyb2xGcmFjdHVyZTEgPC0gZ3JvdXBlZFByb3BvcnRpb25GcmFjdHVyZUNvbnRyb2wgJT4lIGZpbHRlcihjb25kaXRpb249PSJBIikKY29udHJvbEZyYWN0dXJlMiA8LSBncm91cGVkUHJvcG9ydGlvbkZyYWN0dXJlQ29udHJvbCAlPiUgZmlsdGVyKGNvbmRpdGlvbj09IkFwIikKY29udHJvbEZyYWN0dXJlIDwtIGNiaW5kKGNvbnRyb2xGcmFjdHVyZTEsIGNvbnRyb2xGcmFjdHVyZTIpCgpnZ3Bsb3QoY29udHJvbEZyYWN0dXJlLCBhZXMocHJvcCwgcHJvcDEpKSArCiAgZ2VvbV9wb2ludCgpICsKICBnZW9tX2ppdHRlcigpICsgY29vcmRfZml4ZWQoKSArIHhsaW0oMC4wLDEuMCkgKyB5bGltKDAuMCwxLjApICsgbGFicyh0aXRsZT0iUHJvcG9ydGlvbiBvZiB0ZWFtIGZyYWN0dXJlIGluIHRoZSBmaXJzdCB2cy4gdGhpcmQgaW4gY29udHJvbCIsIHN1YnRpdGxlPSJObyBmcmFjdHVyZT0wLCBGcmFjdHVyZT0xIiwgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHg9IkZyYWN0dXJlIHRoZSBmaXJzdCB0aW1lIGEgdGVhbSBpbnRlcmFjdHMiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5PSJGcmFjdHVyZSB0aGUgc2Vjb25kIHRpbWUgYSB0ZWFtIGludGVyYWN0cywgd2l0aG91dCBrbm93aW5nIGl0IikgCgoKZyA8LSBnZ3Bsb3QoZ3JvdXBlZFByb3BvcnRpb25GcmFjdHVyZSwgYWVzKGZhY3RvcihmcmFjdHVyZSksIG1lYW4pKQpnICsgZ2VvbV9ib3hwbG90KHZhcndpZHRoPVQsIGZpbGw9InBsdW0iKSArIAogIGxhYnMoc3VidGl0bGU9IlRlYW0gZnJhY3R1cmUgdmFsdWUgdnMuIG1lYW4gdmlhYmlsaXR5IHNjb3JlOiBmcmFjdHVyZSA+MC41MCIsIAogICAgICAgeD0iIiwKICAgICAgIHk9Ik51bWVyaWMgc3VtIG9mIHZpYWJpbGl0eSBtZWFzdXJlcyBxdWVzdGlvbnMgKHJhbmdlOiA3LTcwKSIpIAoKZyA8LSBnZ3Bsb3QoZ3JvdXBlZFByb3BvcnRpb25GcmFjdHVyZSwgYWVzKGZhY3RvcihmcmFjdHVyZSksIG1lYW4pKSAKZyArIGdlb21fYm94cGxvdCh2YXJ3aWR0aD1ULCBmaWxsPSJwbHVtIikgKyAKICBsYWJzKHN1YnRpdGxlPSJUZWFtIGZyYWN0dXJlIHZhbHVlIHZzLiBtZWFuIHZpYWJpbGl0eSBzY29yZTogZnJhY3R1cmUgPj0wLjUwIiwgCiAgICAgICB4PSIiLAogICAgICAgeT0iTnVtZXJpYyBzdW0gb2YgdmlhYmlsaXR5IG1lYXN1cmVzIHF1ZXN0aW9ucyAocmFuZ2U6IDctNzApIikgCgpnIDwtIGdncGxvdChncm91cGVkUHJvcG9ydGlvbkZyYWN0dXJlVHJlYXRtZW50LCBhZXMoZmFjdG9yKGZyYWN0dXJlKSwgbWVhbikpCmcgKyBnZW9tX2JveHBsb3QodmFyd2lkdGg9VCwgZmlsbD0icGx1bSIpICsgCiAgbGFicyhzdWJ0aXRsZT0iVGVhbSBmcmFjdHVyZSB2YWx1ZSB2cy4gbWVhbiB2aWFiaWxpdHkgc2NvcmU6IGZyYWN0dXJlID4wLjUwIiwgCiAgICAgICB4PSIiLAogICAgICAgeT0iTnVtZXJpYyBzdW0gb2YgdmlhYmlsaXR5IG1lYXN1cmVzIHF1ZXN0aW9ucyAocmFuZ2U6IDctNzApIikgCgoKIyMgRGVmaW5pbmcgZnJhY3R1cmU6IAoKIyMgVFJFQVRNRU5UIEVGRkVDVDogCiMgIyMgT3ZlcmFsbCBmcmFjdHVyZSBjaGFuZ2U6IAojIHN1bShpZmVsc2UodHJlYXRtZW50RnJhY3R1cmUxJGZyYWN0dXJlPT10cmVhdG1lbnRGcmFjdHVyZTIkZnJhY3R1cmUsMCwxKSkgCiMgIyMgTm8gZnJhY3R1cmUgdG8gZnJhY3R1cmU6IAojIHN1bShpZmVsc2UodHJlYXRtZW50RnJhY3R1cmUxJGZyYWN0dXJlPT0wICYgdHJlYXRtZW50RnJhY3R1cmUyJGZyYWN0dXJlPT0xLDEsMCkpCiMgIyMgRnJhY3R1cmUgdG8gbm8gZnJhY3R1cmU6IAojIHN1bShpZmVsc2UodHJlYXRtZW50RnJhY3R1cmUxJGZyYWN0dXJlPT0xICYgdHJlYXRtZW50RnJhY3R1cmUyJGZyYWN0dXJlPT0wLDEsMCkpCiMgIyMgQ09OVFJPTCBFRkZFQ1Q6IAojICMjIE92ZXJhbGwgZnJhY3R1cmUgY2hhbmdlOiAKIyBzdW0oaWZlbHNlKGNvbnRyb2xGcmFjdHVyZTEkZnJhY3R1cmU9PWNvbnRyb2xGcmFjdHVyZTIkZnJhY3R1cmUsMCwxKSkKIyAjIyBObyBmcmFjdHVyZSB0byBmcmFjdHVyZTogCiMgc3VtKGlmZWxzZShjb250cm9sRnJhY3R1cmUxJGZyYWN0dXJlPT0wICYgY29udHJvbEZyYWN0dXJlMiRmcmFjdHVyZT09MSwxLDApKQojICMjIEZyYWN0dXJlIHRvIG5vIGZyYWN0dXJlOiAKIyBzdW0oaWZlbHNlKGNvbnRyb2xGcmFjdHVyZTEkZnJhY3R1cmU9PTEgJiBjb250cm9sRnJhY3R1cmUyJGZyYWN0dXJlPT0wLDEsMCkpCiMgIyMgTEVBUk5JTkcgRUZGRUNUIAojICMjIE92ZXJhbGwgZnJhY3R1cmUgY2hhbmdlOiAKIyBzdW0oaWZlbHNlKGZyYWN0dXJlTEUxJGZyYWN0dXJlPT1mcmFjdHVyZUxFMiRmcmFjdHVyZSwwLDEpKSAKIyAjIyBObyBmcmFjdHVyZSB0byBmcmFjdHVyZToKIyBzdW0oaWZlbHNlKGZyYWN0dXJlTEUxJGZyYWN0dXJlPT0wICYgZnJhY3R1cmVMRTIkZnJhY3R1cmU9PTEsMSwwKSkKIyAjIyBGcmFjdHVyZSB0byBubyBmcmFjdHVyZSAKIyBzdW0oaWZlbHNlKGZyYWN0dXJlTEUxJGZyYWN0dXJlPT0xICYgZnJhY3R1cmVMRTIkZnJhY3R1cmU9PTAsMSwwKSkKYGBgCgojIyAKCgojIyBQcm9iYWJpbGl0eSBvZiBmcmFjdHVyZSBnaXZlbiBjb25kaXRpb24gaW4gdHJlYXRtZW50OiAKYGBge3J9CmNvbmRpdGlvbmFsUHJvYlRyZWF0bWVudCA8LSBncm91cGVkUHJvcG9ydGlvbkZyYWN0dXJlVHJlYXRtZW50ICU+JSBmaWx0ZXIoY29uZGl0aW9uPT0iQSIgfCBjb25kaXRpb249PSJBcCIpCiMjIEdyZWF0ZXIgdGhhbiA1MDogCnRhbGx5KH5mcmFjdHVyZUdyZWF0ZXI1MCB8IGNvbmRpdGlvbiwgZGF0YSA9IGNvbmRpdGlvbmFsUHJvYlRyZWF0bWVudCwgZm9ybWF0ID0gInByb3BvcnRpb24iKQojIyBHcmVhdGVyIG9yIGVxdWFsIDUwOiAKdGFsbHkofmZyYWN0dXJlR3JlYXRlckVxdWFsNTAgfCBjb25kaXRpb24sIGRhdGEgPSBjb25kaXRpb25hbFByb2JUcmVhdG1lbnQsIGZvcm1hdCA9ICJwcm9wb3J0aW9uIikKCmNvbmRpdGlvbmFsUHJvYkNvbnRyb2wgPC0gZ3JvdXBlZFByb3BvcnRpb25Db250cm9sICU+JSBmaWx0ZXIoY29uZGl0aW9uPT0iQSIgfCBjb25kaXRpb249PSJBcCIpCiMjIEdyZWF0ZXIgdGhhbiA1MDogCnRhbGx5KH5mcmFjdHVyZUdyZWF0ZXI1MCB8IGNvbmRpdGlvbiwgZGF0YSA9IGNvbmRpdGlvbmFsUHJvYkNvbnRyb2wsIGZvcm1hdCA9ICJwcm9wb3J0aW9uIikKIyMgR3JlYXRlciBvciBlcXVhbCA1MDogCnRhbGx5KH5mcmFjdHVyZUdyZWF0ZXJFcXVhbDUwIHwgY29uZGl0aW9uLCBkYXRhID0gY29uZGl0aW9uYWxQcm9iQ29udHJvbCwgZm9ybWF0ID0gInByb3BvcnRpb24iKQoKYGBgCgojIyBCb3hwbG90IGZvciBmcmFjdHVyZSBzY29yZXMgdnMuIHZpYWJpbGl0eSBzY29yZSBzdW0gKDctNzApCmBgYHtyfQpncm91cGVkUHJvcG9ydGlvbkZyYWN0dXJlJGZyYWN0dXJlR3JlYXRlcjUwIDwtIGFzLm51bWVyaWMoZ3JvdXBlZFByb3BvcnRpb25GcmFjdHVyZSRmcmFjdHVyZUdyZWF0ZXI1MCkKZ3JvdXBlZFByb3BvcnRpb25GcmFjdHVyZSRmcmFjdHVyZUdyZWF0ZXJFcXVhbDUwIDwtIGFzLm51bWVyaWMoZ3JvdXBlZFByb3BvcnRpb25GcmFjdHVyZSRmcmFjdHVyZUdyZWF0ZXJFcXVhbDUwKQoKZyA8LSBnZ3Bsb3QoZ3JvdXBlZFByb3BvcnRpb25GcmFjdHVyZSwgYWVzKGZhY3RvcihmcmFjdHVyZUdyZWF0ZXI1MCksIG1lZGlhbikpCmcgKyBnZW9tX2JveHBsb3QodmFyd2lkdGg9VCwgZmlsbD0icGx1bSIpICsgCiAgbGFicyhzdWJ0aXRsZT0iVGVhbSBtZWRpYW4gdmlhYmlsaXR5IHNjb3JlIGluIHJlbGF0aW9uIHRvIGJpbmFyeSBmcmFjdHVyZSB2YWx1ZSAoZ3JlYXRlciB0aGFuIDUwKSIsIAogICAgICAgeD0iQmluYXJ5IGZyYWN0dXJlIHZhbHVlIiwKICAgICAgIHk9Ik51bWVyaWMgc3VtIG9mIHZpYWJpbGl0eSBtZWFzdXJlcyBxdWVzdGlvbnMgKHJhbmdlOiA3LTcwKSIpICsgc2NhbGVfeF9kaXNjcmV0ZShsYWJlbHM9YygiMCIgPSAiTm8gRnJhY3R1cmUiLCAiMSIgPSAiRnJhY3R1cmUiKSkgKyBmYWNldF9ncmlkKGNvbmRpdGlvbiB+IHJlc3VsdHMuY29uZGl0aW9uKQoKZyA8LSBnZ3Bsb3QoZ3JvdXBlZFByb3BvcnRpb25GcmFjdHVyZSwgYWVzKGZhY3RvcihmcmFjdHVyZUdyZWF0ZXI1MCksIG1lZGlhbikpCmcgKyBnZW9tX2JveHBsb3QodmFyd2lkdGg9VCwgZmlsbD0icGx1bSIpICsgCiAgbGFicyhzdWJ0aXRsZT0iVGVhbSBtZWRpYW4gdmlhYmlsaXR5IHNjb3JlIGluIHJlbGF0aW9uIHRvIGJpbmFyeSBmcmFjdHVyZSB2YWx1ZSAoZ3JlYXRlciB0aGFuIG9yIGVxdWFsIHRvIDUwKSIsIAogICAgICAgeD0iQmluYXJ5IGZyYWN0dXJlIHZhbHVlIiwKICAgICAgIHk9Ik51bWVyaWMgc3VtIG9mIHZpYWJpbGl0eSBtZWFzdXJlcyBxdWVzdGlvbnMgKHJhbmdlOiA3LTcwKSIpICsgc2NhbGVfeF9kaXNjcmV0ZShsYWJlbHM9YygiMCIgPSAiTm8gRnJhY3R1cmUiLCAiMSIgPSAiRnJhY3R1cmUiKSkgKyBmYWNldF9ncmlkKGNvbmRpdGlvbiB+IHJlc3VsdHMuY29uZGl0aW9uKQoKdHJlYXRtZW50RnJhY3R1cmUxJGZyYWN0dXJlR3JlYXRlcjUwIDwtIGFzLm51bWVyaWModHJlYXRtZW50RnJhY3R1cmUxJGZyYWN0dXJlR3JlYXRlcjUwKSAKdHJlYXRtZW50RnJhY3R1cmUxJGZyYWN0dXJlR3JlYXRlckVxdWFsNTAgPC0gYXMubnVtZXJpYyh0cmVhdG1lbnRGcmFjdHVyZTEkZnJhY3R1cmVHcmVhdGVyRXF1YWw1MCkgCnRyZWF0bWVudEZyYWN0dXJlMiRmcmFjdHVyZUdyZWF0ZXI1MCA8LSBhcy5udW1lcmljKHRyZWF0bWVudEZyYWN0dXJlMiRmcmFjdHVyZUdyZWF0ZXI1MCkgCnRyZWF0bWVudEZyYWN0dXJlMiRmcmFjdHVyZUdyZWF0ZXJFcXVhbDUwIDwtIGFzLm51bWVyaWModHJlYXRtZW50RnJhY3R1cmUyJGZyYWN0dXJlR3JlYXRlckVxdWFsNTApIApjb250cm9sRnJhY3R1cmUxJGZyYWN0dXJlR3JlYXRlcjUwIDwtIGFzLm51bWVyaWMoY29udHJvbEZyYWN0dXJlMSRmcmFjdHVyZUdyZWF0ZXI1MCkKY29udHJvbEZyYWN0dXJlMSRmcmFjdHVyZUdyZWF0ZXJFcXVhbDUwIDwtIGFzLm51bWVyaWMoY29udHJvbEZyYWN0dXJlMSRmcmFjdHVyZUdyZWF0ZXJFcXVhbDUwKQpjb250cm9sRnJhY3R1cmUyJGZyYWN0dXJlR3JlYXRlcjUwIDwtIGFzLm51bWVyaWMoY29udHJvbEZyYWN0dXJlMiRmcmFjdHVyZUdyZWF0ZXI1MCkKY29udHJvbEZyYWN0dXJlMiRmcmFjdHVyZUdyZWF0ZXJFcXVhbDUwIDwtIGFzLm51bWVyaWMoY29udHJvbEZyYWN0dXJlMiRmcmFjdHVyZUdyZWF0ZXJFcXVhbDUwKQpgYGAKCiMjIEFic29sdXRlIGNoYW5nZSBpbiBmcmFjdHVyZSBwcm9wb3J0aW9ucyBiZXR3ZWVuIGNvbmRpdGlvbnM6IApgYGB7cn0KdHJlYXRtZW50RnJhY3R1cmUkYWJzR3JlYXRlcjUwIDwtIGFicyh0cmVhdG1lbnRGcmFjdHVyZTIkZnJhY3R1cmVHcmVhdGVyNTAtdHJlYXRtZW50RnJhY3R1cmUxJGZyYWN0dXJlR3JlYXRlcjUwKQp0cmVhdG1lbnRGcmFjdHVyZSRhYnNFcXVhbEdyZWF0ZXI1MCA8LSBhYnModHJlYXRtZW50RnJhY3R1cmUyJGZyYWN0dXJlR3JlYXRlckVxdWFsNTAtdHJlYXRtZW50RnJhY3R1cmUxJGZyYWN0dXJlR3JlYXRlckVxdWFsNTApCgpnIDwtIGdncGxvdCh0cmVhdG1lbnRGcmFjdHVyZSwgYWVzKGFic0dyZWF0ZXI1MCkpICsgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZSA9ICJTcGVjdHJhbCIpCmcgKyBnZW9tX2hpc3RvZ3JhbShiaW5zPTcsIAogICAgICAgICAgICAgICAgICAgY29sPSJwaW5rIiwgCiAgICAgICAgICAgICAgICAgICBzaXplPS40KSArIAogIGxhYnModGl0bGU9IkFic29sdXRlIGNoYW5nZSBpbiB0ZWFtIGZyYWN0dXJlIHNjb3JlIGluIHRyZWF0bWVudCBjb25kaXRpb24gKGZyYWN0dXJlID4uNTAiLCAKICAgICAgIGZpbGwgPSAiUm91bmQiKSArIAogIHhsYWIobGFiZWw9IkFic29sdXRlIGNoYW5nZSBpbiB0ZWFtIGZyYWN0dXJlIHNjb3JlIGluIHRyZWF0bWVudCBjb25kaXRpb24iKSArIAogIHlsYWIobGFiZWw9IkNvdW50IikgCgpnIDwtIGdncGxvdCh0cmVhdG1lbnRGcmFjdHVyZSwgYWVzKGFic0VxdWFsR3JlYXRlcjUwKSkgKyBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlID0gIlNwZWN0cmFsIikKZyArIGdlb21faGlzdG9ncmFtKGJpbnM9NywgCiAgICAgICAgICAgICAgICAgICBjb2w9InBpbmsiLCAKICAgICAgICAgICAgICAgICAgIHNpemU9LjQpICsgCiAgbGFicyh0aXRsZT0iQWJzb2x1dGUgY2hhbmdlIGluIHRlYW0gZnJhY3R1cmUgc2NvcmUgaW4gdHJlYXRtZW50IGNvbmRpdGlvbiAoZnJhY3R1cmU+PS41MCkiLCAKICAgICAgIGZpbGwgPSAiUm91bmQiKSArIAogIHhsYWIobGFiZWw9IkFic29sdXRlIGNoYW5nZSBpbiB0ZWFtIGZyYWN0dXJlIHNjb3JlIGluIHRyZWF0bWVudCBjb25kaXRpb24iKSArIAogIHlsYWIobGFiZWw9IkNvdW50IikgCgpjb250cm9sRnJhY3R1cmUkYWJzR3JlYXRlcjUwIDwtIGFicyhjb250cm9sRnJhY3R1cmUkZnJhY3R1cmVHcmVhdGVyNTAtY29udHJvbEZyYWN0dXJlMSRmcmFjdHVyZUdyZWF0ZXI1MCkKZyA8LSBnZ3Bsb3QoY29udHJvbEZyYWN0dXJlLCBhZXMoYWJzR3JlYXRlcjUwKSkgKyBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlID0gIlNwZWN0cmFsIikKZyArIGdlb21faGlzdG9ncmFtKGJpbnM9NywgCiAgICAgICAgICAgICAgICAgICBjb2w9InBpbmsiLCAKICAgICAgICAgICAgICAgICAgIHNpemU9LjQpICsgCiAgbGFicyh0aXRsZT0iQWJzb2x1dGUgY2hhbmdlIGluIHRlYW0gZnJhY3R1cmUgc2NvcmUgaW4gY29udHJvbCBjb25kaXRpb24gKGZyYWN0dXJlID4uNTApIiwgCiAgICAgICBmaWxsID0gIlJvdW5kIikgKyAKICB4bGFiKGxhYmVsPSJBYnNvbHV0ZSBjaGFuZ2UgaW4gdGVhbSBmcmFjdHVyZSBzY29yZSBpbiBjb250cm9sIGNvbmRpdGlvbiIpICsgCiAgeWxhYihsYWJlbD0iQ291bnQiKSAKCmNvbnRyb2xGcmFjdHVyZSRhYnNFcXVhbEdyZWF0ZXI1MCA8LSBhYnMoY29udHJvbEZyYWN0dXJlJGZyYWN0dXJlR3JlYXRlckVxdWFsNTAtY29udHJvbEZyYWN0dXJlMSRmcmFjdHVyZUdyZWF0ZXJFcXVhbDUwKQpnIDwtIGdncGxvdChjb250cm9sRnJhY3R1cmUsIGFlcyhhYnNFcXVhbEdyZWF0ZXI1MCkpICsgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZSA9ICJTcGVjdHJhbCIpCmcgKyBnZW9tX2hpc3RvZ3JhbShiaW5zPTcsIAogICAgICAgICAgICAgICAgICAgY29sPSJwaW5rIiwgCiAgICAgICAgICAgICAgICAgICBzaXplPS40KSArIAogIGxhYnModGl0bGU9IkFic29sdXRlIGNoYW5nZSBpbiB0ZWFtIGZyYWN0dXJlIHNjb3JlIGluIGNvbnRyb2wgY29uZGl0aW9uIChmcmFjdHVyZSA+PS41MCkiLCAKICAgICAgIGZpbGwgPSAiUm91bmQiKSArIAogIHhsYWIobGFiZWw9IkFic29sdXRlIGNoYW5nZSBpbiB0ZWFtIGZyYWN0dXJlIHNjb3JlIGluIGNvbnRyb2wgY29uZGl0aW9uIikgKyAKICB5bGFiKGxhYmVsPSJDb3VudCIpIAoKY29udHJvbEZyYWN0dXJlJGFic0dyZWF0ZXJFcXVhbDUwIDwtIGFicyhjb250cm9sRnJhY3R1cmUkZnJhY3R1cmVHcmVhdGVyRXF1YWw1MC1jb250cm9sRnJhY3R1cmUxJGZyYWN0dXJlR3JlYXRlckVxdWFsNTApCmcgPC0gZ2dwbG90KGNvbnRyb2xGcmFjdHVyZSwgYWVzKGFicykpICsgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZSA9ICJTcGVjdHJhbCIpCmcgKyBnZW9tX2hpc3RvZ3JhbShiaW5zPTcsIAogICAgICAgICAgICAgICAgICAgY29sPSJwaW5rIiwgCiAgICAgICAgICAgICAgICAgICBzaXplPS40KSArIAogIGxhYnModGl0bGU9IkFic29sdXRlIGNoYW5nZSBpbiB0ZWFtIGZyYWN0dXJlIHNjb3JlIGluIGNvbnRyb2wgY29uZGl0aW9uIChmcmFjdHVyZSA+PS41MCkiLCAKICAgICAgIGZpbGwgPSAiUm91bmQiKSArIAogIHhsYWIobGFiZWw9IkFic29sdXRlIGNoYW5nZSBpbiB0ZWFtIGZyYWN0dXJlIHNjb3JlIGluIGNvbnRyb2wgY29uZGl0aW9uIikgKyAKICB5bGFiKGxhYmVsPSJDb3VudCIpIAoKdHJlYXRtZW50RnJhY3R1cmVFcXVhbEdyZWF0ZXJBYnNTdW0gPC0gc3VtKHRyZWF0bWVudEZyYWN0dXJlJGFic0VxdWFsR3JlYXRlcjUwKSAKdHJlYXRtZW50RnJhY3R1cmVHcmVhdGVyQWJzU3VtIDwtIHN1bSh0cmVhdG1lbnRGcmFjdHVyZSRhYnNHcmVhdGVyNTApCgojIyBWaXN1YWxpemUgZGlmZmVyZW5jZXM6IAoKZGF0IDwtIGRhdGEuZnJhbWUoY2hhbmdlc1BlckZyYWN0dXJlRGVmaW5pdGlvbiA9IGZhY3RvcihjKCJTdW0gb2YgYWJzb2x1dGUgZnJhY3R1cmUgY2hhbmdlIGluIHRyZWF0bWVudCA+LjUwIiwiU3VtIG9mIGFic29sdXRlIGZyYWN0dXJlIGNoYW5nZSBpbiB0cmVhdG1lbnQgPj0uNTAiKSwgbGV2ZWxzPWMoIlN1bSBvZiBhYnNvbHV0ZSBmcmFjdHVyZSBjaGFuZ2UgaW4gdHJlYXRtZW50ID4uNTAiLCJTdW0gb2YgYWJzb2x1dGUgZnJhY3R1cmUgY2hhbmdlIGluIHRyZWF0bWVudCA+PS41MCIpKSwKICAgICAgICAgICAgICAgICAgZnJhY3R1cmVWYWx1ZUNoYW5nZSA9IGMoOCwgMTkpKQoKcCA8LSBnZ3Bsb3QoZGF0YT1kYXQsIGFlcyh4PWNoYW5nZXNQZXJGcmFjdHVyZURlZmluaXRpb24sIHk9ZnJhY3R1cmVWYWx1ZUNoYW5nZSkpICsKICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIpCnAgPC0gZ2dwbG90bHkocCkKcAoKdHJlYXRtZW50RnJhY3R1cmVFcXVhbEdyZWF0ZXJBYnNTdW0gPC0gc3VtKHRyZWF0bWVudEZyYWN0dXJlJGFic0VxdWFsR3JlYXRlcjUwKSAKY29udHJvbEZyYWN0dXJlRXF1YWxHcmVhdGVyQWJzU3VtIDwtIHN1bShjb250cm9sRnJhY3R1cmUkYWJzR3JlYXRlckVxdWFsNTApCnRyZWF0bWVudEZyYWN0dXJlR3JlYXRlckFic1N1bSA8LSBzdW0odHJlYXRtZW50RnJhY3R1cmUkYWJzR3JlYXRlcjUwKQpjb250cm9sRnJhY3R1cmVHcmVhdGVyQWJzU3VtIDwtIHN1bShjb250cm9sRnJhY3R1cmUkYWJzR3JlYXRlcjUwKQoKZGF0IDwtIGRhdGEuZnJhbWUoY2hhbmdlc1BlckZyYWN0dXJlRGVmaW5pdGlvbiA9IGZhY3RvcihjKCJTdW0gb2YgYWJzb2x1dGUgZnJhY3R1cmUgY2hhbmdlIGluIHRyZWF0bWVudCA+LjUwIiwiU3VtIG9mIGFic29sdXRlIGZyYWN0dXJlIGNoYW5nZSBpbiBjb250cm9sID4uNTAiKSwgbGV2ZWxzPWMoIlN1bSBvZiBhYnNvbHV0ZSBmcmFjdHVyZSBjaGFuZ2UgaW4gdHJlYXRtZW50ID4uNTAiLCJTdW0gb2YgYWJzb2x1dGUgZnJhY3R1cmUgY2hhbmdlIGluIGNvbnRyb2wgPi41MCIpKSwKICAgICAgICAgICAgICAgICAgZnJhY3R1cmVWYWx1ZUNoYW5nZSA9IGMoWCwgWCkpCgpwIDwtIGdncGxvdChkYXRhPWRhdCwgYWVzKHg9Y2hhbmdlc1BlckZyYWN0dXJlRGVmaW5pdGlvbiwgeT1mcmFjdHVyZVZhbHVlQ2hhbmdlKSkgKwogIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IikKcCA8LSBnZ3Bsb3RseShwKQpwCgpkYXQgPC0gZGF0YS5mcmFtZShjaGFuZ2VzUGVyRnJhY3R1cmVEZWZpbml0aW9uID0gZmFjdG9yKGMoIlN1bSBvZiBhYnNvbHV0ZSBmcmFjdHVyZSBjaGFuZ2UgaW4gdHJlYXRtZW50ID49LjUwIiwiU3VtIG9mIGFic29sdXRlIGZyYWN0dXJlIGNoYW5nZSBpbiBjb250cm9sID49LjUwIiksIGxldmVscz1jKCJTdW0gb2YgYWJzb2x1dGUgZnJhY3R1cmUgY2hhbmdlIGluIHRyZWF0bWVudCA+PS41MCIsIlN1bSBvZiBhYnNvbHV0ZSBmcmFjdHVyZSBjaGFuZ2UgaW4gY29udHJvbCA+PS41MCIpKSwKICAgICAgICAgICAgICAgICAgZnJhY3R1cmVWYWx1ZUNoYW5nZSA9IGMoOCwgMTkpKQoKcCA8LSBnZ3Bsb3QoZGF0YT1kYXQsIGFlcyh4PWNoYW5nZXNQZXJGcmFjdHVyZURlZmluaXRpb24sIHk9ZnJhY3R1cmVWYWx1ZUNoYW5nZSkpICsKICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIpCnAgPC0gZ2dwbG90bHkocCkKcApgYGAKCmBgYHtyfQoKYGBgCgoKCgojIyBIaXN0b2dyYW0gY29tcGFyaXNvbnMgb2YgZnJhY3R1cmUgcmF0aW9zIGFjcm9zcyB0cmVhdG1lbnQsIGNvbnRyb2wgYW5kIGxlYXJuaW5nIGVmZmVjdCBjb25kaXRpb25zCgpgYGB7cn0KZ2dwbG90KGRhdGE9Z3JvdXBlZFByb3BvcnRpb25GcmFjdHVyZVRyZWF0bWVudCwgYWVzKGZyYWN0dXJlKSkgKyAKICBnZW9tX2JhcihicmVha3M9c2VxKDAsIDEsIGJ5PTAuMjApLCAKICAgICAgICAgICAgICAgICBjb2w9InJlZCIsIAogICAgICAgICAgICAgICAgIGZpbGw9ImdyZWVuIiwgCiAgICAgICAgICAgICAgICAgYWxwaGE9LjIpICsgbGFicyh0aXRsZT0iRnJhY3R1cmUgcmF0aW9zOiB0cmVhdG1lbnQgY29uZGl0aW9uIikgKyBmYWNldF9ncmlkKGNvbmRpdGlvbiB+IHJlc3VsdHMuY29uZGl0aW9uKQoKZ2dwbG90KGRhdGE9Z3JvdXBlZFByb3BvcnRpb25GcmFjdHVyZUNvbnRyb2wsIGFlcyhmcmFjdHVyZSkpICsgCiAgZ2VvbV9iYXIoYnJlYWtzPXNlcSgwLCAxLCBieT0wLjIwKSwgCiAgICAgICAgICAgICAgICAgY29sPSJyZWQiLCAKICAgICAgICAgICAgICAgICBmaWxsPSJncmVlbiIsIAogICAgICAgICAgICAgICAgIGFscGhhPS4yKSArIGxhYnModGl0bGU9IkZyYWN0dXJlIHJhdGlvczogY29udHJvbCByb3VuZCIpICsgZmFjZXRfZ3JpZChjb25kaXRpb24gfiByZXN1bHRzLmNvbmRpdGlvbikKCmdncGxvdChkYXRhPWdyb3VwZWRQcm9wb3J0aW9uRnJhY3R1cmVMRSwgYWVzKGZyYWN0dXJlKSkgKyAKICBnZW9tX2JhcihicmVha3M9c2VxKDAsIDEsIGJ5PTAuMjApLCAKICAgICAgICAgICAgICAgICBjb2w9InJlZCIsIAogICAgICAgICAgICAgICAgIGZpbGw9ImdyZWVuIiwgCiAgICAgICAgICAgICAgICAgYWxwaGE9LjIpICsgbGFicyh0aXRsZT0iRnJhY3R1cmUgcmF0aW9zOiBsZWFybmluZyBlZmZlY3QgY29uZGl0aW9uIikgKyBmYWNldF9ncmlkKHJlc3VsdHMuY29uZGl0aW9uIH4gcm91bmQpCgpgYGAKCiMjIEdyYXBocyBmb3IgbWVhbiBkaXN0cmJ1dGlvbiBwZXIgdHJlYXRtZW50IGNvbmRpdGlvbjogCgpgYGB7cn0KIyMgTWVhbiB2aWFiaWxpdHkgZGlzdHJpYnV0aW9uIGdyYXBoOiB0cmVhdG1lbnQgY29uZGl0aW9uLCBBIGdyb3VwIApiYXJmaWxsIDwtICIjNDI3MUFFIgpiYXJsaW5lcyA8LSAiIzFGMzU1MiIKIyMgTWVhbiBmb3IgdHJlYXRtZW50IGFuZCBBIGdyb3VwOiAjI2ZpbGwtaW4pIAptZWFuRGlzdHJpYnV0aW9uVHJlYXRtZW50QSA8LSBnZ3Bsb3QodHJlYXRtZW50QVN0YXRzLCBhZXMoeCA9IHN1bSkpICsKICBnZW9tX2hpc3RvZ3JhbShhZXMoeSA9IC4uY291bnQuLiksIGJpbndpZHRoID0gNSwKICAgICAgICAgICAgICAgICBjb2xvdXIgPSBiYXJsaW5lcywgZmlsbCA9IGJhcmZpbGwpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobmFtZSA9ICJNZWRpYW4gdmlhYmlsaXR5IHN1bSIsCiAgICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IHNlcSgwLCAxMDAsIDIwKSwKICAgICAgICAgICAgICAgICAgICAgbGltaXRzPWMoMCwgNzApKSArCiAgc2NhbGVfeV9jb250aW51b3VzKG5hbWUgPSAiY291bnQiKSArCiAgZ2d0aXRsZSgiRnJlcXVlbmN5IG9mIHN1bSBvZiB2aWFiaWxpdHkgc2NvcmVzOiBOPSMjZmlsbC1pbiIpICsKICB0aGVtZV9idygpICsKICB0aGVtZShheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoc2l6ZT0xLCBjb2xvdXIgPSAiYmxhY2siKSwKICAgICAgICBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9saW5lKGNvbG91ciA9ICIjZDNkM2QzIiksCiAgICAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X2JsYW5rKCksIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQsIGZhbWlseSA9ICJUYWhvbWEiLCBmYWNlID0gImJvbGQiKSwKICAgICAgICB0ZXh0PWVsZW1lbnRfdGV4dChmYW1pbHk9IlRhaG9tYSIpLAogICAgICAgIGF4aXMudGV4dC54PWVsZW1lbnRfdGV4dChjb2xvdXI9ImJsYWNrIiwgc2l6ZSA9IDkpLAogICAgICAgIGF4aXMudGV4dC55PWVsZW1lbnRfdGV4dChjb2xvdXI9ImJsYWNrIiwgc2l6ZSA9IDkpKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gIyNmaWxsLWluLCBzaXplID0gMSwgY29sb3VyID0gIiNGRjM3MjEiLAogICAgICAgICAgICAgICBsaW5ldHlwZSA9ICJkYXNoZWQiKQptZWFuRGlzdHJpYnV0aW9uVHJlYXRtZW50QQoKIyMgTWVhbiB2aWFiaWxpdHkgZGlzdHJpYnV0aW9uIGdyYXBoOiB0cmVhdG1lbnQgY29uZGl0aW9uLCBBcHJpbWUgZ3JvdXAgCiMjIE1lYW4gZm9yIHRyZWF0bWVudCBjb25kaXRpb24sIEFwcmltZSBncm91cDogKGZpbGwtaW4pCm1lYW5EaXN0cmlidXRpb25UcmVhdG1lbnRBcCA8LSBnZ3Bsb3QodHJlYXRtZW50QXBTdGF0cywgYWVzKHggPSBzdW0pKSArCiAgZ2VvbV9oaXN0b2dyYW0oYWVzKHkgPSAuLmNvdW50Li4pLCBiaW53aWR0aCA9IDUsCiAgICAgICAgICAgICAgICAgY29sb3VyID0gYmFybGluZXMsIGZpbGwgPSBiYXJmaWxsKSArCiAgc2NhbGVfeF9jb250aW51b3VzKG5hbWUgPSAiTWVkaWFuIHZpYWJpbGl0eSBzdW0iLAogICAgICAgICAgICAgICAgICAgICBicmVha3MgPSBzZXEoMCwgMTAwLCAyMCksCiAgICAgICAgICAgICAgICAgICAgIGxpbWl0cz1jKDAsIDcwKSkgKwogIHNjYWxlX3lfY29udGludW91cyhuYW1lID0gImNvdW50IikgKwogIGdndGl0bGUoIkZyZXF1ZW5jeSBvZiBzdW0gb2YgdmlhYmlsaXR5IHNjb3JlczpOPSMjZmlsbC1pbiIpICsKICB0aGVtZV9idygpICsKICB0aGVtZShheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoc2l6ZT0xLCBjb2xvdXIgPSAiYmxhY2siKSwKICAgICAgICBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9saW5lKGNvbG91ciA9ICIjZDNkM2QzIiksCiAgICAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X2JsYW5rKCksIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQsIGZhbWlseSA9ICJUYWhvbWEiLCBmYWNlID0gImJvbGQiKSwKICAgICAgICB0ZXh0PWVsZW1lbnRfdGV4dChmYW1pbHk9IlRhaG9tYSIpLAogICAgICAgIGF4aXMudGV4dC54PWVsZW1lbnRfdGV4dChjb2xvdXI9ImJsYWNrIiwgc2l6ZSA9IDkpLAogICAgICAgIGF4aXMudGV4dC55PWVsZW1lbnRfdGV4dChjb2xvdXI9ImJsYWNrIiwgc2l6ZSA9IDkpKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gIyNmaWxsLWluLCBzaXplID0gMSwgY29sb3VyID0gIiNGRjM3MjEiLAogICAgICAgICAgICAgICBsaW5ldHlwZSA9ICJkYXNoZWQiKQptZWFuRGlzdHJpYnV0aW9uVHJlYXRtZW50QXAKCiMjIE1lYW4gdmlhYmlsaXR5IGRpc3RyaWJ1dGlvbiBncmFwaDogdHJlYXRtZW50IGNvbmRpdGlvbiwgQiBncm91cCAKIyMgTWVhbiBmb3IgdHJlYXRtZW50IGNvbmRpdGlvbiwgQiBncm91cDogCmJhcmZpbGwgPC0gIiM0MjcxQUUiCmJhcmxpbmVzIDwtICIjMUYzNTUyIgptZWFuRGlzdHJpYnV0aW9uVHJlYXRtZW50QiA8LSBnZ3Bsb3QodHJlYXRtZW50QlN0YXRzLCBhZXMoeCA9IHN1bSkpICsKICBnZW9tX2hpc3RvZ3JhbShhZXMoeSA9IC4uY291bnQuLiksIGJpbndpZHRoID0gNSwKICAgICAgICAgICAgICAgICBjb2xvdXIgPSBiYXJsaW5lcywgZmlsbCA9IGJhcmZpbGwpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobmFtZSA9ICJNZWRpYW4gdmlhYmlsaXR5IHN1bSBcbiBhY3Jvc3MgYWxsIHRlYW1zIGluIG1hc2tlZCByb3VuZCIsCiAgICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IHNlcSgwLCA5OCwgMTQpLAogICAgICAgICAgICAgICAgICAgICBsaW1pdHM9Yyg3LCA3MCkpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobmFtZSA9ICJjb3VudCIpICsKICBnZ3RpdGxlKCJGcmVxdWVuY3kgb2Ygc3VtIG9mIHZpYWJpbGl0eSBzY29yZXM6IG1hc2tlZCBjb25kaXRpb24sIE49IyNmaWxsLWluIikgKwogIHRoZW1lX2J3KCkgKwogIHRoZW1lKGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShzaXplPTEsIGNvbG91ciA9ICJibGFjayIpLAogICAgICAgIHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gIiNkM2QzZDMiKSwKICAgICAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfYmxhbmsoKSwgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgZmFtaWx5ID0gIlRhaG9tYSIsIGZhY2UgPSAiYm9sZCIpLAogICAgICAgIHRleHQ9ZWxlbWVudF90ZXh0KGZhbWlseT0iVGFob21hIiksCiAgICAgICAgYXhpcy50ZXh0Lng9ZWxlbWVudF90ZXh0KGNvbG91cj0iYmxhY2siLCBzaXplID0gOSksCiAgICAgICAgYXhpcy50ZXh0Lnk9ZWxlbWVudF90ZXh0KGNvbG91cj0iYmxhY2siLCBzaXplID0gOSkpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAjI2ZpbGwtaW4sIHNpemUgPSAxLCBjb2xvdXIgPSAiI0ZGMzcyMSIsCiAgICAgICAgICAgICAgIGxpbmV0eXBlID0gImRhc2hlZCIpIAptZWFuRGlzdHJpYnV0aW9uVHJlYXRtZW50QgpgYGAKCiMjIENoYXQgZGF0YTogCmBgYHtyfQpjaGF0RmlsZXMgPSBsYXBwbHkoY29tcGxldGVCYXRjaGVzLCBmdW5jdGlvbihiYXRjaCl7CiAgICBjaGF0RmlsZSA9IHJlYWRfanNvbihwYXN0ZShkYXRhUGF0aCxiYXRjaCwiY2hhdHMuanNvbiIsc2VwPSIvIiksIHNpbXBsaWZ5VmVjdG9yID0gVFJVRSkKICAgIHJldHVybihmbGF0dGVuKGNoYXRGaWxlLCByZWN1cnNpdmUgPSBUUlVFKSkKICB9KQoKYWxsQ2hhdEZpbGVzIDwtIHBseXI6OmxkcGx5KGNoYXRGaWxlcywgZGF0YS5mcmFtZSkKY2hhdEZyZXEgPC0gYWxsQ2hhdEZpbGVzICAlPiUKICBncm91cF9ieShyb3VuZCwgcm9vbSwgYmF0Y2gpICU+JSAKICBkcGx5cjo6c3VtbWFyaXNlKG49bigpKSAlPiUgCiAgZmlsdGVyKG4+MSwgcm91bmQ8PTIpCgojIyBGaWx0ZXIgb24gcm91bmQgPD0yLCBiZWNhdXNlIHJvdW5kIDMgaW4gYWxsIGJ1dCBvbmUgY2FzZSBpcyBvbmx5IGluY2x1ZGVzICJYIGhhcyBsZWZ0IGNoYXQgcm9vbSIgCgojIEhpc3RvZ3JhbSBncm91cGVkIGJ5IHJvdW5kOiAKZyA8LSBnZ3Bsb3QoY2hhdEZyZXEsIGFlcyhuKSkgKyBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlID0gIlNwZWN0cmFsIikKZyArIGdlb21faGlzdG9ncmFtKGFlcyhmaWxsPWZhY3Rvcihyb3VuZCkpLCAKICAgICAgICAgICAgICAgICAgIGJpbnM9NSwgCiAgICAgICAgICAgICAgICAgICBjb2w9ImJsYWNrIiwgCiAgICAgICAgICAgICAgICAgICBzaXplPS4xKSArICAgIyBjaGFuZ2UgbnVtYmVyIG9mIGJpbnMKICBsYWJzKHRpdGxlPSJIaXN0b2dyYW0gb2YgdGhlIG51bWJlciBvZiBjaGF0IGxpbmVzIHBlciB0ZWFtIChpbmNsdWRlcyB0ZWFtcyB3aXRoIG49MSkiLCAKICAgICAgIGZpbGwgPSAiUm91bmQiKSArIAogIHhsYWIobGFiZWw9Ik51bWJlciBvZiBsaW5lcyBmcm9tIGNoYXQgZGF0YSBwZXIgdGVhbSIpICsgCiAgeWxhYihsYWJlbD0iQ291bnQiKSAKc3RhdHMkcm9vbSA8LSB1bmxpc3Qoc3RhdHMkcm9vbSkgCmNoYXRGcmVxU3RhdHMgPC0gcmlnaHRfam9pbih4PWNoYXRGcmVxLCB5PXN0YXRzKQoKCiMjIEV4cG9ydCBjaGF0IGRhdGEgZm9yIE1hdjogCndyaXRlLmNzdihhbGxDaGF0RmlsZXMsIGZpbGUgPSAiYWxsQ2hhdEZpbGVzLmNzdiIpCgpgYGAKCiMjIENvbmRpdGlvbmFsIHByb2JhYmlsaXRpZXM6IApgYGB7cn0KZ3JvdXBlZFByb3BvcnRpb25GcmFjdHVyZVRyZWF0bWVudCAlPiUgCiAgZ3JvdXBfYnkoY29uZGl0aW9uKSAlPiUgCiAgc3VtbWFyaXNlKG49bigpLCBjb3VudD1jb3VudChmcmFjdHVyZSkpIAoKIyBQKEYzfEYxKSAKcDEgPC0gIDE5IC8gMzQKCiMgUChub3RGM3xGMSkgCnAyIDwtICAxNSAvIDM0CgojIFAoRjN8RjEpCnAzIDwtIDI0IC8gMzQKCiMjIFAobm90RjN8RjEpCnA0IDwtIDEwIC8gMzQKCiAgIyBQcmludCBvdXQgdGhlIHByb2JhYmlsaXRpZXMKcm91bmQoYyhwMSwgcDIsIHAzLCBwNCksIGRpZ2l0cyA9IDIpICAKCgpgYGAKCgoK